chore(release): backport staging fixes onto patch-1.93.0rc2 for the 1.93.0 stable cut - #33847
Conversation
(cherry picked from commit 20e646c)
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)
#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)
…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)
|
|
Greptile SummaryThis is a release stabilization backport that cherry-picks 11 fixes and dependency bumps from staging onto
Confidence Score: 4/5Safe 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.
|
| 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)
-
litellm/proxy/utils.py, line 6152-6159 (link)First-deployment wins for multi-deployment model groups
get_configured_token_limitscallsget_deployment_by_model_group_name, which returns only the first deployment for a givenmodel_name. When a model group has multiple deployments with differentmodel_info.max_input_tokens/max_output_tokens(e.g., one deployment at 128k and another at 200k), the/v1/modelsresponse 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 previousget_model_group_infoaggregation 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: |
There was a problem hiding this comment.
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.
PR overviewThis 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 |
Relevant issues
Promotes
v1.93.0-rc.2into the 1.93.0 stable cut. Backports 11 staging PRs ontopatch-1.93.0rc2, a fresh base branch created at the exactv1.93.0-rc.2tag 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 cutsv1.93.0once that landsLinear ticket
Pre-Submission checklist
What is included
Cherry-picks in original staging merge order, all
-xtraceable tolitellm_internal_staging:fix(ci): bump pillow to 12.3.0 to resolve osv-scan CVEs (verbatim)chore(deps): pin httplib2 and setuptools transitive floors (lock regenerated on the line)fix(anthropic/passthrough): drop incompatible temperature when downgrading adaptive thinking for pre-4.6 models (adapted, see notes)build: raise requires-python cap to <3.15 so Python 3.14 installs current releases (lock regenerated on the line)build(deps): update ddtrace to the 4.x line (lock regenerated on the line; picked as its single content commitedc38eab34)fix(docker): restore litellm-proxy-extras source dir in runtime images (verbatim)fix(model_armor): restore reference attachments via skip_unscannable_attachments and remove the attachment count cap (verbatim)build(rust): raise pyo3 to 0.29 so the native bridge compiles on Python 3.14 (verbatim)build(deps): allow redisvl, pypdf, and openapi-core on Python 3.14 (lock regenerated on the line)build(deps): bump mcp lock to 1.28.1 to clear image-scan findings (adapted, see notes)fix(proxy): source /v1/models token limits from the cost map instead of Router.get_model_group_info (verbatim)No version bump: rc2's
pyproject.tomlalready reads1.93.0and finalv1.93.0is unreleased (DockerHub and GHCR both 404, nov1.93.0tag, norelease/v1.93.0branch; only the rc images are published). The picks ride the pending1.93.0. No production.tsxis touched, so there is no UI rebuildBase branch and provenance
Base is
patch-1.93.0rc2, a new branch created at the exactv1.93.0-rc.2commit (b5cd431c1e);git diff v1.93.0-rc.2 patch-1.93.0rc2is empty. Every commit on this PR carries a(cherry picked from commit ...)footer whose SHA is reachable fromlitellm_internal_staging, original authorship is preserved, and there are no merge commits and no_experimental/out/artifactsAdaptation notes
Five dependency picks (#33233, #33438, #33484, #33801, #33803) hit
uv.lockcontext conflicts because the line's lock differs from staging's. Each was resolved by taking the pick'spyproject.tomlchange and regenerating the lock on the line with uv itself (uv lock, anduv lock --upgrade-package mcpfor #33803, mirroring that PR's own operation); no lock hunk was hand-merged. Thepyproject.tomlhunks 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 --checkpasses anduv sync --frozen --all-groups --all-extrasinstalls cleanly on the branchTwo picks needed source-level context resolution:
831dbbc4df(not picked) later moved_cap_thinking_budget_to_max_tokensfromAnthropicMessagesConfigtoAnthropicConfig, and the pick's context assumed that move. The resolution keeps the line's local_cap_thinking_budget_to_max_tokensand itsAnthropicMessagesConfig.call site untouched and adds only the pick's own_drop_incompatible_temperature_for_thinkingmethod and its call site. A name-equality check confirms the resolved diff adds exactly the defs the staging PR adds, in source and testslitellm-proxy-extras/litellm-enterprisepins 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_urlfails on the untouched rc2 baseline (it expectshttp://0.0.0.0:4000/litellm/ui/and a local environment resolveshttp://localhost...). It is the same single failure before and after the picks and is unrelated to themScreenshots / Proof of Fix
Targeted test delta, captured at
44b3de5a83(all 11 picks) versusb5cd431c1e(rc2 baseline), same six-file targeted set (the test files the picks touch plus their mirrored files):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:After, at
44b3de5a83(same request):The downgraded thinking is preserved and the incompatible pinned temperature is dropped, which is exactly the pick's contract
Live
/v1/models?include_metadata=truebefore/after (#33721): config-mapped models keep identicalmax_input_tokens/max_output_tokens, while models whose limits previously came fromRouter.get_model_group_infoaggregation 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 buildoflitellm-rustcompletes on this branch with pyo3 0.29 (Finished dev profile), so no call site drifted on the lineDependency 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 targetingpatch-*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 #33869Type
🐛 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.0rc2so the release flow can cutv1.93.0from that branch once merged, following thepatch-1.92.0rc2->stable/1.92.xprecedent