feat(ptu): configure provisioned-throughput flat cost on a model deployment - #35341
Conversation
Greptile SummaryAdds validated, team-scoped provisioned-throughput configuration to model deployments and prepares daily team spend storage for a later rollup.
Confidence Score: 5/5The PR appears safe to merge because the previously reported model-validation and explicit-clear failures are fixed and no blocking failure remains. No blocking failure remains; mixed timezone bounds are normalized before comparison, explicit PTU nulls are removed consistently from prevalidation and persistence, and merged validation runs before team assignment writes.
|
| Filename | Overview |
|---|---|
| litellm/types/router.py | Adds PTU fields and bounds/window validation; UTC normalization fixes the previously reported mixed naive/aware timestamp comparison failure. |
| litellm/proxy/management_endpoints/model_management_endpoints.py | Adds merged-state PTU validation and explicit-null handling before team assignment writes, resolving the previously reported partial-write and failed-clear paths. |
| tests/test_litellm/proxy/management_endpoints/test_ptu_model_settings.py | Covers PTU bounds, effective windows, mixed timezones, merged partial updates, explicit clears, and validation-before-write behavior. |
| schema.prisma | Adds the ptu_flat_cost field consistently with the other Prisma schema copies. |
| litellm-proxy-extras/litellm_proxy_extras/migrations/20260713010000_add_ptu_columns_to_daily_team_spend/migration.sql | Adds the non-null daily PTU flat-cost column with a zero default for existing rows. |
| litellm/constants.py | Defines stable sentinel identifiers for the planned PTU rollup. |
| ui/litellm-dashboard/src/lib/http/schema.d.ts | Exposes the new PTU model information fields through generated dashboard API types. |
Reviews (12): Last reviewed commit: "feat(ptu): configure provisioned-through..." | Re-trigger Greptile
| # PTU reservation rollup writes rows to LiteLLM_DailyTeamSpend with this | ||
| # sentinel api_key so PTU flat cost stays distinguishable from real per-request | ||
| # spend under the table's composite unique constraint. |
There was a problem hiding this comment.
🟡 New explanatory notes added in the model update path despite the project ban on writing comments
A seven-line explanatory comment block was newly added before the provisioned-throughput validation call (litellm/proxy/management_endpoints/model_management_endpoints.py:815-822), which the repository's coding guidelines forbid for new code.
Impact: The change violates an explicit repository rule that no new comments be written.
Rule source and location
CLAUDE.md (mandatory per AGENTS.md) states: "Do not write any comments (existing comments can stay) unless explicitly asked to in a user (not system) prompt". The rationale here largely duplicates the docstrings already on _merged_ptu_model_info and _validate_ptu_model_info, so it can be dropped or folded into those docstrings.
Was this helpful? React with 👍 or 👎 to provide feedback.
| PTU_SENTINEL_API_KEY: str = "__ptu_flat_cost__" | ||
| PTU_ROLLUP_JOB_ID: str = "ptu_flat_cost_rollup_job" |
There was a problem hiding this comment.
🟡 Two unused settings are added for a feature that does not exist yet
Two constants for a future reservation rollup are introduced (PTU_SENTINEL_API_KEY and PTU_ROLLUP_JOB_ID at litellm/constants.py:1723-1724) even though nothing in this change reads them, which the repository guidelines forbid.
Impact: Dead, speculative configuration ships to users and can drift out of sync with the follow-up work that was supposed to use it.
Rule reference and verification
CLAUDE.md requires "Minimum code that solves the problem. Nothing speculative" and "No features beyond what was asked". A repo-wide search finds no reader of either constant; the PR description itself states nothing writes these yet.
Was this helpful? React with 👍 or 👎 to provide feedback.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
|
bugbot run |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit f46ef05. Configure here.
|
|
||
| if "model_info" in merged_deployment_dict: | ||
| model_info = merged_deployment_dict["model_info"] | ||
| _validate_ptu_model_info(model_info) |
There was a problem hiding this comment.
Merged PTU window not validated
High Severity
The _validate_ptu_model_info function doesn't check that ptu_effective_to is after ptu_effective_from. This allows invalid PTU date ranges to be persisted. When these models are later loaded, ModelInfo validation fails, potentially dropping models from the live router or blocking updates.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit f46ef05. Configure here.
f46ef05 to
0ba04eb
Compare
|
@greptileai fixed: the effective window now rejects to <= from with a 400, and clearing a PTU field removes it from model_info. Re-review please |
0ba04eb to
921718c
Compare
|
@greptileai the effective-window check now coerces naive and offset-aware timestamps to UTC before comparing, so mixed-awareness inputs no longer crash parsing. Re-review please |
|
@greptileai rebased onto the updated base with no content change; the naive/aware timestamp-comparison fix is unchanged. Re-review please |
921718c to
9a58b7f
Compare
|
@greptileai rebased onto current staging; the PTU window is now validated before the count/rate gate so a one-ended patch cannot persist an inverted window. Re-review please |
9a58b7f to
dbb579d
Compare
|
@greptileai review Rebased onto current staging, resolving conflicts in constants, router types, and the model update endpoint. Please re-review |
dbb579d to
277f096
Compare
|
@greptileai review Annotated the new PTU locals as Final to clear the type-discipline budget. Rebased onto current staging |
277f096 to
d0c36fc
Compare
d0c36fc to
1b3c5df
Compare
|
@greptileai review The update path validates the merged model_info now, so raising the rate on a configured model is no longer rejected for carrying no start |
fdcf8aa to
c0ab5d2
Compare
|
@greptileai review |
c0ab5d2 to
e79641d
Compare
|
@greptileai review latest head |
e79641d to
bb150c5
Compare
|
@greptileai review |
|
|
||
| monkeypatch.setattr(mme, "_setup_new_team_model_assignment", _never) | ||
| monkeypatch.setattr(mme, "_update_existing_team_model_assignment", _never) | ||
| monkeypatch.setattr(mme.ModelManagementAuthChecks, "allow_team_model_action", AsyncMock(return_value=True)) |
There was a problem hiding this comment.
🟡 New tests replace parts of a class at runtime instead of injecting dependencies
The new tests swap out an authorization method on a shared class at runtime (monkeypatch.setattr(mme.ModelManagementAuthChecks, ...) at tests/test_litellm/proxy/management_endpoints/test_ptu_model_settings.py:325), which the repository's guidelines call an anti-pattern.
Impact: The test approach violates an explicit repository testing rule.
Rule source
CLAUDE.md states: "Monkeypatching attributes of a class to do testing is an anti-pattern. Prefer dependency-injecting things into classes. That way, at unit test time, you can pass a mocked dependency in". The helper at tests/test_litellm/proxy/management_endpoints/test_ptu_model_settings.py:315-332 patches both module-level functions and the ModelManagementAuthChecks.allow_team_model_action class attribute; the class-attribute patch is the one the rule names directly.
Was this helpful? React with 👍 or 👎 to provide feedback.
…oyment
Add ptu_count, cost_per_ptu_per_hour, ptu_effective_from and ptu_effective_to to
ModelInfo so a model deployment can carry the inputs for provisioned-throughput
flat-cost attribution. ModelInfo validates per-field bounds (positive count,
non-negative rate, effective_to after effective_from); model/new and
model/{id}/update enforce the cross-field invariant (count and rate set together,
team_id required) on the effective model_info so partial updates validate the
merged result, and v1/model/info returns the fields.
LiteLLM_DailyTeamSpend gains ptu_flat_cost and ptu_source_model_id columns plus a
sentinel api_key constant; the daily rollup that writes them lands in a follow-up
PR. Adding the optional model_info fields is backward compatible; models without
them are unaffected.
ptu_effective_from is required alongside the count and rate rather than optional. Flat
cost accrues from that instant, so an absent start has to be inferred, and inferring it
let a deployment configured today be billed for days it did not exist. Both PTU validators
also run over the merged view before any write on the update path, beside the premium check the create path
already runs there: the team ACL update below autocommits, so a validator raising further
down left the team mutated and the deployment row never written.
The update path validates the model_info a patch would store rather than the patch
alone. An invariant holds over the deployment as it will exist, not over whichever
subset of fields a caller sent, and validating the patch rejected raising the rate on
an already configured model because that patch carries no start of its own.
bb150c5 to
d2be1ce
Compare
|
@greptileai review |
…8.0) (#393)
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
| [ghcr.io/berriai/litellm](https://images.chainguard.dev/directory/image/wolfi-base/overview) ([source](https://github.com/BerriAI/litellm)) | minor | `v1.97.0` → `v1.98.0` |
---
### Release Notes
<details>
<summary>BerriAI/litellm (ghcr.io/berriai/litellm)</summary>
### [`v1.98.0`](https://github.com/BerriAI/litellm/releases/tag/v1.98.0)
[Compare Source](https://github.com/BerriAI/litellm/compare/v1.98.0...v1.98.0)
##### Verify Docker Image Signature
All LiteLLM Docker images are signed with [cosign](https://docs.sigstore.dev/cosign/overview/). Every release is signed with the same key introduced in [commit `0112e53`](https://github.com/BerriAI/litellm/commit/0112e53046018d726492c814b3644b7d376029d0).
**Verify using the pinned commit hash (recommended):**
A commit hash is cryptographically immutable, so this is the strongest way to ensure you are using the original signing key:
```bash
cosign verify \
--key https://raw.githubusercontent.com/BerriAI/litellm/0112e53046018d726492c814b3644b7d376029d0/cosign.pub \
ghcr.io/berriai/litellm:v1.98.0
```
**Verify using the release tag (convenience):**
Tags are protected in this repository and resolve to the same key. This option is easier to read but relies on tag protection rules:
```bash
cosign verify \
--key https://raw.githubusercontent.com/BerriAI/litellm/v1.98.0/cosign.pub \
ghcr.io/berriai/litellm:v1.98.0
```
Expected output:
```
The following checks were performed on each of these signatures:
- The cosign claims were validated
- The signatures were verified against the specified public key
```
***
##### What's Changed
- fix(bedrock): drop toolSpec.strict for Claude Sonnet 5 on Converse by [@​kr0k](https://github.com/kr0k) in [#​33196](https://github.com/BerriAI/litellm/pull/33196)
- fix(batches): attribute Vertex passthrough batch cost to key/team/tags by [@​yucheng-berri](https://github.com/yucheng-berri) in [#​34456](https://github.com/BerriAI/litellm/pull/34456)
- docs: rewrite the CLAUDE.md comment rule with explicit exceptions by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36301](https://github.com/BerriAI/litellm/pull/36301)
- fix(proxy): scope file list pagination cursors to the caller by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36093](https://github.com/BerriAI/litellm/pull/36093)
- fix(proxy): skip prisma-dependent hooks when no database is attached by [@​mateo-berri](https://github.com/mateo-berri) in [#​36273](https://github.com/BerriAI/litellm/pull/36273)
- fix(proxy): report has\_more false on caller-scoped file list pages by [@​mateo-berri](https://github.com/mateo-berri) in [#​36326](https://github.com/BerriAI/litellm/pull/36326)
- fix(proxy): restore management\_v1 query-param validation under fastapi>=0.140.7 by [@​HuanQian571](https://github.com/HuanQian571) in [#​35773](https://github.com/BerriAI/litellm/pull/35773)
- fix(proxy): stop /{provider}/v1/files from capturing /openai\_passthrough by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36092](https://github.com/BerriAI/litellm/pull/36092)
- chore(typing): remove 914 basedpyright Any errors across 16 hotspot files by [@​mateo-berri](https://github.com/mateo-berri) in [#​36386](https://github.com/BerriAI/litellm/pull/36386)
- fix(router): keep batch fallbacks inside the model group that owns the file by [@​mateo-berri](https://github.com/mateo-berri) in [#​36181](https://github.com/BerriAI/litellm/pull/36181)
- feat(ptu): configure provisioned-throughput flat cost on a model deployment by [@​yucheng-berri](https://github.com/yucheng-berri) in [#​35341](https://github.com/BerriAI/litellm/pull/35341)
- docs: clarify the CLAUDE.md comment exceptions are any-of by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36421](https://github.com/BerriAI/litellm/pull/36421)
- docs: replace the Changes PR template section with Caveats by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36423](https://github.com/BerriAI/litellm/pull/36423)
- fix(bedrock): enable native structured output for GLM 5 and DeepSeek V3.2 by [@​alexshtf](https://github.com/alexshtf) in [#​35669](https://github.com/BerriAI/litellm/pull/35669)
- feat(ptu): daily rollup writes per-model PTU flat cost by active hour by [@​yucheng-berri](https://github.com/yucheng-berri) in [#​35343](https://github.com/BerriAI/litellm/pull/35343)
- feat(logging): add opt-in session\_id and trace\_id correlation to JSON log records via contextvars by [@​deepanshululla](https://github.com/deepanshululla) in [#​34418](https://github.com/BerriAI/litellm/pull/34418)
- feat(ptu): surface PTU flat cost on the daily activity read path by [@​yucheng-berri](https://github.com/yucheng-berri) in [#​35391](https://github.com/BerriAI/litellm/pull/35391)
- feat(router): add per-deployment allowed\_fails\_policy and cooldown\_time override support by [@​deepanshululla](https://github.com/deepanshululla) in [#​34416](https://github.com/BerriAI/litellm/pull/34416)
- feat(ptu): add PTU inputs to the model form and flat cost to the Usage page by [@​yucheng-berri](https://github.com/yucheng-berri) in [#​35393](https://github.com/BerriAI/litellm/pull/35393)
- fix(cost): price dict-shaped image input token details at the image rate by [@​vairodp](https://github.com/vairodp) in [#​33490](https://github.com/BerriAI/litellm/pull/33490)
- fix(model\_prices): refresh deprecation dates, correct xAI pricing and add missing provider models by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36403](https://github.com/BerriAI/litellm/pull/36403)
- feat(ptu): gate PTU flat-cost attribution behind an opt-in env var by [@​yucheng-berri](https://github.com/yucheng-berri) in [#​36138](https://github.com/BerriAI/litellm/pull/36138)
- ci: cache Prisma CLI and engine binaries, split test timeout from setup by [@​mateo-berri](https://github.com/mateo-berri) in [#​36417](https://github.com/BerriAI/litellm/pull/36417)
- feat(rate limiting): configurable estimated output tokens per key, team and model by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36143](https://github.com/BerriAI/litellm/pull/36143)
- fix(ui): hide admin-only Logs tabs from roles that cannot call their endpoints by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36333](https://github.com/BerriAI/litellm/pull/36333)
- test(proxy): guard management\_v1 against fastapi names removed in supported releases by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36336](https://github.com/BerriAI/litellm/pull/36336)
- fix(ui): gate policy and prompt lookups on an admin capability by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36335](https://github.com/BerriAI/litellm/pull/36335)
- build(deps): bump pypdf to 6.15.0 to clear osv-scan by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36350](https://github.com/BerriAI/litellm/pull/36350)
- fix(proxy): isolate guardrail load failures per row by [@​yucheng-berri](https://github.com/yucheng-berri) in [#​36432](https://github.com/BerriAI/litellm/pull/36432)
- fix(ui): gate organization and agent usage views behind capabilities by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36334](https://github.com/BerriAI/litellm/pull/36334)
- fix(reset\_budget\_job): atomic budget cascade with chunked reset scans by [@​ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#​36287](https://github.com/BerriAI/litellm/pull/36287)
- feat(proxy): add GET /v1/indexes to list vector store indexes by [@​ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#​36289](https://github.com/BerriAI/litellm/pull/36289)
- feat(ui): show vector store indexes on the Vector Stores page by [@​ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#​36306](https://github.com/BerriAI/litellm/pull/36306)
- fix(proxy): treat SAML as configured in UI SSO detection by [@​fancybear-dev](https://github.com/fancybear-dev) in [#​36196](https://github.com/BerriAI/litellm/pull/36196)
- fix(bedrock): reject Anthropic server-side web\_search tool with actionable error by [@​ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#​36473](https://github.com/BerriAI/litellm/pull/36473)
- fix(ui): open the classifier prompt editor above the edit auto-router form by [@​tin-berri](https://github.com/tin-berri) in [#​36438](https://github.com/BerriAI/litellm/pull/36438)
- fix(arize): trace MCP tool calls instead of crashing on CallToolResult by [@​yucheng-berri](https://github.com/yucheng-berri) in [#​36453](https://github.com/BerriAI/litellm/pull/36453)
- refactor(ui): make illegal DataTable prop combinations unrepresentable by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36470](https://github.com/BerriAI/litellm/pull/36470)
- fix(ui): scope Virtual Keys and Logs team lists to the caller by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36472](https://github.com/BerriAI/litellm/pull/36472)
- fix(ui): gate the Old Usage page behind a proxy-admin capability by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36469](https://github.com/BerriAI/litellm/pull/36469)
- docs(terraform): describe the provider release as automatic by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36467](https://github.com/BerriAI/litellm/pull/36467)
- feat(proxy): add per-deployment keepalive\_seconds SSE heartbeat to prevent load-balancer timeout on long streams by [@​deepanshululla](https://github.com/deepanshululla) in [#​34423](https://github.com/BerriAI/litellm/pull/34423)
- fix(router): cool down failed fallback deployments and correct cooldown TTL after Redis backfill by [@​deepanshululla](https://github.com/deepanshululla) in [#​35104](https://github.com/BerriAI/litellm/pull/35104)
- perf(spend): write each daily spend batch in one upsert statement by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36448](https://github.com/BerriAI/litellm/pull/36448)
- fix(ui): gate four sidebar pages on the roles their endpoints allow by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36475](https://github.com/BerriAI/litellm/pull/36475)
- fix(ui): restore the Logs Deleted Teams tab for organization admins by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36478](https://github.com/BerriAI/litellm/pull/36478)
- fix(websearch): stop leaking interception control fields to providers by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36480](https://github.com/BerriAI/litellm/pull/36480)
- test(e2e): cover the Anthropic web\_search server tool on Bedrock by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36443](https://github.com/BerriAI/litellm/pull/36443)
- fix(router): warn when a deployment's credentials contradict its provider by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36486](https://github.com/BerriAI/litellm/pull/36486)
- fix: net prompt-caching savings against the cache-write premium by [@​tin-berri](https://github.com/tin-berri) in [#​36452](https://github.com/BerriAI/litellm/pull/36452)
- feat(ui): deployment affinity toggle for the auto-router by [@​tin-berri](https://github.com/tin-berri) in [#​36302](https://github.com/BerriAI/litellm/pull/36302)
- fix(bedrock): use deployment credentials for AWS requests by [@​daleselaji-dev](https://github.com/daleselaji-dev) in [#​36160](https://github.com/BerriAI/litellm/pull/36160)
- fix(anthropic): preserve midturn system corrections by [@​eugene-yao-zocdoc](https://github.com/eugene-yao-zocdoc) in [#​34290](https://github.com/BerriAI/litellm/pull/34290)
- fix(email): stop duplicate legacy invitation email and fix its onboarding link by [@​mubashir1osmani](https://github.com/mubashir1osmani) in [#​36455](https://github.com/BerriAI/litellm/pull/36455)
- feat(ui): show models under each tier in routing benchmark chart by [@​tin-berri](https://github.com/tin-berri) in [#​36291](https://github.com/BerriAI/litellm/pull/36291)
- fix(proxy): inject streaming usage cost on openai passthrough streams by [@​mateo-berri](https://github.com/mateo-berri) in [#​36503](https://github.com/BerriAI/litellm/pull/36503)
- docs: require a user flow and live-proxy proof in bug reports by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36498](https://github.com/BerriAI/litellm/pull/36498)
- fix(proxy): add config\_updated\_at audit timestamp for virtual keys by [@​ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#​36488](https://github.com/BerriAI/litellm/pull/36488)
- docs: require a user flow and a stuck-at proof in feature requests by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36500](https://github.com/BerriAI/litellm/pull/36500)
- feat(router): add required-AND (&) tag prefix and allow\_fail\_open flag by [@​deepanshululla](https://github.com/deepanshululla) in [#​36193](https://github.com/BerriAI/litellm/pull/36193)
- feat(proxy): per-key prompt caching toggle via enable\_prompt\_caching by [@​ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#​36466](https://github.com/BerriAI/litellm/pull/36466)
- fix(bedrock): send tool-search beta header for Haiku 4.5 on Invoke /v1/messages by [@​mateo-berri](https://github.com/mateo-berri) in [#​36502](https://github.com/BerriAI/litellm/pull/36502)
- fix(bedrock): preserve adaptive thinking effort through the /v1/messages bridge by [@​mateo-berri](https://github.com/mateo-berri) in [#​36507](https://github.com/BerriAI/litellm/pull/36507)
- ci: retry transient network fetch failures in lint workflow by [@​mateo-berri](https://github.com/mateo-berri) in [#​36563](https://github.com/BerriAI/litellm/pull/36563)
- fix(ui): stub useIsOrgAdmin in UsageTab tests so useCan needs no QueryClient by [@​ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#​36565](https://github.com/BerriAI/litellm/pull/36565)
- fix(alerting): dedupe scheduled Slack spend reports across pods by [@​ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#​36489](https://github.com/BerriAI/litellm/pull/36489)
- chore(typing): clear 1.6k basedpyright Any errors across 56 files by [@​mateo-berri](https://github.com/mateo-berri) in [#​36543](https://github.com/BerriAI/litellm/pull/36543)
- fix(bedrock): add text block to converse user messages carrying documents by [@​mateo-berri](https://github.com/mateo-berri) in [#​36499](https://github.com/BerriAI/litellm/pull/36499)
- fix(deps): ship boto3 with the base SDK so bedrock works out of the box by [@​mubashir1osmani](https://github.com/mubashir1osmani) in [#​36568](https://github.com/BerriAI/litellm/pull/36568)
- fix(model\_prices): add provider-announced deprecation dates for Bedrock, Mistral, Cohere and Gemini models by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36538](https://github.com/BerriAI/litellm/pull/36538)
- chore: bump litellm-enterprise 0.1.54 -> 0.1.55, litellm-proxy-extras 0.4.84 -> 0.4.85, litellm 1.97.0 -> 1.98.0 by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36577](https://github.com/BerriAI/litellm/pull/36577)
- fix(bedrock\_guardrails): skip ApplyGuardrail when there is no content to scan by [@​yucheng-berri](https://github.com/yucheng-berri) in [#​36441](https://github.com/BerriAI/litellm/pull/36441)
- fix(e2e): assert on the gen-AI span that served the stream, not the span count by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36582](https://github.com/BerriAI/litellm/pull/36582)
- test(e2e): harden vendor API coverage by [@​mubashir1osmani](https://github.com/mubashir1osmani) in [#​34557](https://github.com/BerriAI/litellm/pull/34557)
- test(e2e): add reproducers for passthrough and model budget gaps by [@​mubashir1osmani](https://github.com/mubashir1osmani) in [#​34657](https://github.com/BerriAI/litellm/pull/34657)
- test(e2e): cover google-native generateContent framing and prometheus queue time by [@​mubashir1osmani](https://github.com/mubashir1osmani) in [#​34650](https://github.com/BerriAI/litellm/pull/34650)
- chore(ci): promote internal staging to main by [@​tin-berri](https://github.com/tin-berri) in [#​36560](https://github.com/BerriAI/litellm/pull/36560)
- feat(router): make routing groups callable as virtual models and list them in /v1/models by [@​tin-berri](https://github.com/tin-berri) in [#​36519](https://github.com/BerriAI/litellm/pull/36519)
- fix(xai): bill web\_search from server\_side\_tool\_usage\_details by [@​geraint0923](https://github.com/geraint0923) in [#​30817](https://github.com/BerriAI/litellm/pull/30817)
- fix(responses): init completed\_response on bridge streaming iterator ([#​35411](https://github.com/BerriAI/litellm/issues/35411)) by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​35413](https://github.com/BerriAI/litellm/pull/35413)
- fix(batches): attribute Anthropic passthrough batch cost to the creating key, team and tags by [@​yucheng-berri](https://github.com/yucheng-berri) in [#​36468](https://github.com/BerriAI/litellm/pull/36468)
- feat(dashscope): add latest Model Studio models to the cost map by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36496](https://github.com/BerriAI/litellm/pull/36496)
- fix(proxy): track streamed passthrough Responses cost by [@​william-xue](https://github.com/william-xue) in [#​36529](https://github.com/BerriAI/litellm/pull/36529)
- fix(model\_prices): advertise native structured output on every Bedrock DeepSeek V3.2 and GLM 5 id by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36597](https://github.com/BerriAI/litellm/pull/36597)
- test(bedrock): repoint live Claude tests off the retired Claude 3 Sonnet by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36600](https://github.com/BerriAI/litellm/pull/36600)
- fix(anthropic): preserve speed=fast in usage for /v1/messages and pass-through by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36447](https://github.com/BerriAI/litellm/pull/36447)
- fix(proxy): forward resolved provider and deployment pricing in /cost/estimate by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​35880](https://github.com/BerriAI/litellm/pull/35880)
- feat(proxy): global SSE keepalive ping interval for OpenAI-shaped streaming routes by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36154](https://github.com/BerriAI/litellm/pull/36154)
- fix(responses): preserve Codex namespace tool calls by [@​dcadenas](https://github.com/dcadenas) in [#​32536](https://github.com/BerriAI/litellm/pull/32536)
- fix(nvidia\_nim): preserve image passages and stop sending top\_k to /v1/ranking by [@​atomic](https://github.com/atomic) in [#​34177](https://github.com/BerriAI/litellm/pull/34177)
- fix: refactor HTTP handler initialization with client support by [@​Praveen11558](https://github.com/Praveen11558) in [#​30952](https://github.com/BerriAI/litellm/pull/30952)
- feat(lint): gate writable TypedDict fields with LIT012 by [@​mateo-berri](https://github.com/mateo-berri) in [#​36590](https://github.com/BerriAI/litellm/pull/36590)
- perf(proxy): stagger scheduled background jobs across jobs and pods by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36589](https://github.com/BerriAI/litellm/pull/36589)
- test: remove four mirror test files that exercise none of their module by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​34635](https://github.com/BerriAI/litellm/pull/34635)
- fix(router): stop re-applying router-selecting request tags to the routed tier's deployments by [@​mateo-berri](https://github.com/mateo-berri) in [#​36628](https://github.com/BerriAI/litellm/pull/36628)
- test: remove tests that never execute by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36681](https://github.com/BerriAI/litellm/pull/36681)
- fix(ui): align spend and budget columns by [@​daniel-meismer-zocdoc](https://github.com/daniel-meismer-zocdoc) in [#​35176](https://github.com/BerriAI/litellm/pull/35176)
- test: rename tests that a later definition shadowed by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36685](https://github.com/BerriAI/litellm/pull/36685)
- fix(passthrough): carry the budget reservation into request metadata by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36592](https://github.com/BerriAI/litellm/pull/36592)
- fix(mcp): bound MCP client requests with a session read timeout by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36675](https://github.com/BerriAI/litellm/pull/36675)
- fix(proxy): log requests rejected for an unparsable body in spend logs by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36673](https://github.com/BerriAI/litellm/pull/36673)
- refactor(ui): migrate cost-optimization to shadcn by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36629](https://github.com/BerriAI/litellm/pull/36629)
- refactor(ui): migrate cost-tracking to shadcn by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36631](https://github.com/BerriAI/litellm/pull/36631)
- refactor(ui): migrate admin-panel to shadcn by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36635](https://github.com/BerriAI/litellm/pull/36635)
- refactor(ui): migrate users dashboard to shadcn by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36642](https://github.com/BerriAI/litellm/pull/36642)
- refactor(ui): migrate prompts to shadcn by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36643](https://github.com/BerriAI/litellm/pull/36643)
- refactor(ui): migrate team settings to shadcn by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36641](https://github.com/BerriAI/litellm/pull/36641)
- refactor(ui): migrate models-and-endpoints to shadcn by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36648](https://github.com/BerriAI/litellm/pull/36648)
- refactor(ui): migrate policy impact popover to shadcn by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36653](https://github.com/BerriAI/litellm/pull/36653)
- fix(proxy): expand config-defined model access groups when resolving team models for /v2/model/info by [@​ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#​34211](https://github.com/BerriAI/litellm/pull/34211)
- fix(batches): strip NUL bytes from passthrough batch tags before the managed object write by [@​yucheng-berri](https://github.com/yucheng-berri) in [#​36688](https://github.com/BerriAI/litellm/pull/36688)
- test(e2e-ui): verify UI mutations against the API instead of trusting the toast by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36632](https://github.com/BerriAI/litellm/pull/36632)
- fix(proxy): serialize model reconciles so concurrent model writes stop evicting each other by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36687](https://github.com/BerriAI/litellm/pull/36687)
- chore(e2e): port the compat-matrix cron publisher to tests/e2e/claude\_code by [@​mateo-berri](https://github.com/mateo-berri) in [#​36465](https://github.com/BerriAI/litellm/pull/36465)
- fix(router): never price a strategy-router alias by [@​tin-berri](https://github.com/tin-berri) in [#​36691](https://github.com/BerriAI/litellm/pull/36691)
- feat(model\_prices): add NVIDIA Nemotron 3.5 Lightning on OpenRouter and DeepInfra by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36696](https://github.com/BerriAI/litellm/pull/36696)
- feat(terraform/aws): make VPC, Aurora, and Redis optional by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36676](https://github.com/BerriAI/litellm/pull/36676)
- feat(ui): warn in the Admin UI when no Redis is configured by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36495](https://github.com/BerriAI/litellm/pull/36495)
- fix(ui): show and edit key-level router settings on a virtual key by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36674](https://github.com/BerriAI/litellm/pull/36674)
- fix(router): forward auto-router alias params from the marker entry, not the first same-name deployment by [@​mateo-berri](https://github.com/mateo-berri) in [#​36626](https://github.com/BerriAI/litellm/pull/36626)
- fix(bedrock\_mantle): 1M context window and long-context pricing for GPT-5.6 Sol/Terra/Luna by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36698](https://github.com/BerriAI/litellm/pull/36698)
- fix(model\_prices): sync the Groq registry with Groq's docs by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36664](https://github.com/BerriAI/litellm/pull/36664)
- fix(router): let untagged requests bypass a tagged pre-routing strategy on shared model names by [@​mateo-berri](https://github.com/mateo-berri) in [#​36627](https://github.com/BerriAI/litellm/pull/36627)
- fix(spend): stop losing spend log rows when a flush is cancelled by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​34826](https://github.com/BerriAI/litellm/pull/34826)
- docs(claude): drop the @​ prefix from the PR template path by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36726](https://github.com/BerriAI/litellm/pull/36726)
- fix(langfuse): emit otel trace version and release on the keys langfuse v4 reads by [@​yucheng-berri](https://github.com/yucheng-berri) in [#​36702](https://github.com/BerriAI/litellm/pull/36702)
- test(interactions): follow Google spec drift replacing Turn with typed steps by [@​mateo-berri](https://github.com/mateo-berri) in [#​36730](https://github.com/BerriAI/litellm/pull/36730)
- refactor(ui): migrate team detail controls to shadcn by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36695](https://github.com/BerriAI/litellm/pull/36695)
- refactor(ui): migrate guardrail and duration controls to shadcn by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36693](https://github.com/BerriAI/litellm/pull/36693)
- refactor(ui): migrate guardrails-monitor, projects, logs to shadcn by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​34606](https://github.com/BerriAI/litellm/pull/34606)
- refactor(ui): migrate search and user controls to shadcn by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36694](https://github.com/BerriAI/litellm/pull/36694)
- fix(guardrails): scan and re-emit raw Anthropic SSE streams in the bedrock post-call hook by [@​yucheng-berri](https://github.com/yucheng-berri) in [#​36598](https://github.com/BerriAI/litellm/pull/36598)
- fix(helm): render nodeSelector on the migrations job by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36747](https://github.com/BerriAI/litellm/pull/36747)
- fix(langfuse): coerce header-sourced mask and trace-update steering values by [@​yucheng-berri](https://github.com/yucheng-berri) in [#​36740](https://github.com/BerriAI/litellm/pull/36740)
- refactor(ui): migrate usage tables to shared DataTable by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36707](https://github.com/BerriAI/litellm/pull/36707)
- refactor(ui): migrate guardrails monitor table to shared DataTable by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36709](https://github.com/BerriAI/litellm/pull/36709)
- refactor(ui): migrate guardrails content tables to shared DataTable by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36708](https://github.com/BerriAI/litellm/pull/36708)
- feat(gemini): day-0 pricing for gemini-3.7-flash by [@​mateo-berri](https://github.com/mateo-berri) in [#​36792](https://github.com/BerriAI/litellm/pull/36792)
- ci: promote staging to main by [@​mateo-berri](https://github.com/mateo-berri) in [#​36725](https://github.com/BerriAI/litellm/pull/36725)
- build(deps): bump nanoid to 3.3.18 to clear osv-scan by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36787](https://github.com/BerriAI/litellm/pull/36787)
- fix(router): stop scoring system prompt text for code/technical complexity by [@​tin-berri](https://github.com/tin-berri) in [#​36721](https://github.com/BerriAI/litellm/pull/36721)
- feat(complexity\_router): calibrate the classifier rubric with worked examples, selectable per router by [@​tin-berri](https://github.com/tin-berri) in [#​36578](https://github.com/BerriAI/litellm/pull/36578)
- fix(interactions): map step and turn history to Responses API roles and content types by [@​mateo-berri](https://github.com/mateo-berri) in [#​36733](https://github.com/BerriAI/litellm/pull/36733)
- fix(ui): restore playground model filtering by endpoint by [@​mubashir1osmani](https://github.com/mubashir1osmani) in [#​36130](https://github.com/BerriAI/litellm/pull/36130)
- fix(proxy/batches): stop forwarding custom\_llm\_provider twice in list and cancel by [@​anxkhn](https://github.com/anxkhn) in [#​32813](https://github.com/BerriAI/litellm/pull/32813)
- refactor(ui): migrate TokenFlow and JsonViewer to shadcn by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36735](https://github.com/BerriAI/litellm/pull/36735)
- feat: pre-adoption shadow eval for the auto-router (blind pairwise judge, derived state) by [@​tin-berri](https://github.com/tin-berri) in [#​36587](https://github.com/BerriAI/litellm/pull/36587)
- refactor(ui): migrate SimpleMessageBlock and SimpleToolCallBlock to shadcn by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36737](https://github.com/BerriAI/litellm/pull/36737)
- refactor(ui): migrate HistoryTree and CollapsibleMessage to shadcn by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36738](https://github.com/BerriAI/litellm/pull/36738)
- refactor: replace Any with precise types across responses, proxy, and llms modules by [@​mateo-berri](https://github.com/mateo-berri) in [#​36763](https://github.com/BerriAI/litellm/pull/36763)
- refactor(ui): migrate TruncatedValue and OutputCard to shadcn by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36739](https://github.com/BerriAI/litellm/pull/36739)
- refactor(ui): migrate SectionHeader and ToolsSection to shadcn by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36793](https://github.com/BerriAI/litellm/pull/36793)
- feat(ui): migrate playground chat controls to shadcn by [@​mubashir1osmani](https://github.com/mubashir1osmani) in [#​36129](https://github.com/BerriAI/litellm/pull/36129)
- feat(xai): day-0 pricing for grok-4.6 by [@​mateo-berri](https://github.com/mateo-berri) in [#​36805](https://github.com/BerriAI/litellm/pull/36805)
- feat(ui): highlight Auto Router in the navbar announcement by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36315](https://github.com/BerriAI/litellm/pull/36315)
- test(e2e): assert the model allow-list permits, not only denies by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36823](https://github.com/BerriAI/litellm/pull/36823)
- fix(proxy): tolerate a concurrent creator when creating spend views by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36824](https://github.com/BerriAI/litellm/pull/36824)
- fix(proxy): honor explicit null budget\_duration on team and key create + clearable UI dropdowns by [@​ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#​36699](https://github.com/BerriAI/litellm/pull/36699)
- feat(model\_prices): add meta/muse-spark-1.2 and its contributor tier by [@​mateo-berri](https://github.com/mateo-berri) in [#​36717](https://github.com/BerriAI/litellm/pull/36717)
- fix(auth): carry team grants in lite login session tokens by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36826](https://github.com/BerriAI/litellm/pull/36826)
- feat(ui): show provider prompt cache tokens in chat response metrics by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36827](https://github.com/BerriAI/litellm/pull/36827)
- fix(auth): stop the team fallback from widening model access by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36837](https://github.com/BerriAI/litellm/pull/36837)
- fix(proxy/team): resolve member\_delete cleanup by user id, not the addressed email by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36839](https://github.com/BerriAI/litellm/pull/36839)
- fix(cli): launch agents as a child process on Windows by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36822](https://github.com/BerriAI/litellm/pull/36822)
- feat(ui): shadow evals tab beside auto-router usage by [@​tin-berri](https://github.com/tin-berri) in [#​36588](https://github.com/BerriAI/litellm/pull/36588)
- feat(cli): make the hidden `lite` command list configurable by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36816](https://github.com/BerriAI/litellm/pull/36816)
- feat(azure\_ai): add Fireworks FW model pricing on Azure AI Foundry by [@​emerzon](https://github.com/emerzon) in [#​35613](https://github.com/BerriAI/litellm/pull/35613)
- fix: enable xhigh reasoning support for gpt-5.4-mini models by [@​emerzon](https://github.com/emerzon) in [#​26909](https://github.com/BerriAI/litellm/pull/26909)
- feat(azure-ai): add Grok 4.3 model metadata by [@​emerzon](https://github.com/emerzon) in [#​27932](https://github.com/BerriAI/litellm/pull/27932)
- feat(ui): render request metrics on the /ui/chat surface by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36845](https://github.com/BerriAI/litellm/pull/36845)
- fix(ui): stop a deselected MCP server keeping its grant on a virtual key by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36840](https://github.com/BerriAI/litellm/pull/36840)
- fix(team): sweep dangling team references and cache on team delete by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36819](https://github.com/BerriAI/litellm/pull/36819)
- fix(mcp): resolve admin OAuth sessions from any worker via DB-backed drafts by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36844](https://github.com/BerriAI/litellm/pull/36844)
- refactor(ui): migrate usage to shadcn by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36834](https://github.com/BerriAI/litellm/pull/36834)
- refactor(ui): migrate guardrails-monitor to shadcn by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36838](https://github.com/BerriAI/litellm/pull/36838)
- refactor(ui): migrate playground to shadcn by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36847](https://github.com/BerriAI/litellm/pull/36847)
- refactor(ui): migrate guardrails to shadcn by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36832](https://github.com/BerriAI/litellm/pull/36832)
- fix(batches): stop uncostable batches from starving the cost poll page by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36714](https://github.com/BerriAI/litellm/pull/36714)
- perf(spend-logs): bound retention cleanup so one run cannot saturate the database by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36594](https://github.com/BerriAI/litellm/pull/36594)
- fix(proxy): fail config load when a callbacks entry is not dispatchable by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36858](https://github.com/BerriAI/litellm/pull/36858)
- fix(bedrock): hoist custom.defer\_loading before dropping custom on invoke tools by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36855](https://github.com/BerriAI/litellm/pull/36855)
- fix(access groups): sync assigned\_key\_ids from the key write paths by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36843](https://github.com/BerriAI/litellm/pull/36843)
- fix(mcp): expose client HTTP headers to logging callbacks and hooks by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36724](https://github.com/BerriAI/litellm/pull/36724)
- fix(ptu): stop per-token billing on a PTU-configured deployment by [@​yucheng-berri](https://github.com/yucheng-berri) in [#​36829](https://github.com/BerriAI/litellm/pull/36829)
- fix(ui): add nvidia riva to the model provider list by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36769](https://github.com/BerriAI/litellm/pull/36769)
- fix(scripts): end make check with a ran/skipped summary and verdict by [@​mateo-berri](https://github.com/mateo-berri) in [#​36864](https://github.com/BerriAI/litellm/pull/36864)
- fix(proxy): track spend for OpenAI passthrough /v1/embeddings by [@​lostmartian](https://github.com/lostmartian) in [#​36660](https://github.com/BerriAI/litellm/pull/36660)
- test(proxy): stop monkeypatch.undo re-planting fixture-mocked prisma\_client by [@​mateo-berri](https://github.com/mateo-berri) in [#​36872](https://github.com/BerriAI/litellm/pull/36872)
- fix(access groups): sync assigned\_team\_ids from the team write paths by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36825](https://github.com/BerriAI/litellm/pull/36825)
- ci: drop the CircleCI ui\_build and ui\_unit\_tests jobs by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36893](https://github.com/BerriAI/litellm/pull/36893)
- fix(langfuse)!: source the emitted metadata blob from StandardLoggingPayload by [@​yucheng-berri](https://github.com/yucheng-berri) in [#​36744](https://github.com/BerriAI/litellm/pull/36744)
- refactor(ui): migrate Navbar off antd to shadcn by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36902](https://github.com/BerriAI/litellm/pull/36902)
- refactor(ui): migrate log details drawer off antd to shadcn by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36904](https://github.com/BerriAI/litellm/pull/36904)
- refactor(ui): migrate AI Hub off antd and tremor to shadcn by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36908](https://github.com/BerriAI/litellm/pull/36908)
- refactor(ui): move the shared dropdowns and selectors onto shadcn primitives by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36924](https://github.com/BerriAI/litellm/pull/36924)
- refactor(ui): move the root-level dashboard components onto shadcn primitives by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36927](https://github.com/BerriAI/litellm/pull/36927)
- refactor(ui): move the settings page and bulk user invite onto shadcn primitives by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36936](https://github.com/BerriAI/litellm/pull/36936)
- refactor(ui): move the cost tracking components onto shadcn primitives by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36955](https://github.com/BerriAI/litellm/pull/36955)
- ci: drop the duplicate proxy\_unit\_tests letter-shard workflow by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36866](https://github.com/BerriAI/litellm/pull/36866)
- refactor(ui): migrate shared common\_components off antd and tremor by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36910](https://github.com/BerriAI/litellm/pull/36910)
- refactor(ui): migrate key info and permissions views off antd and tremor by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36913](https://github.com/BerriAI/litellm/pull/36913)
- feat(proxy): serve Anthropic-native /v1/models for Claude Code gateway discovery by [@​Ar-maan05](https://github.com/Ar-maan05) in [#​35455](https://github.com/BerriAI/litellm/pull/35455)
- refactor(ui): migrate router settings and shared badges off antd and tremor by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36915](https://github.com/BerriAI/litellm/pull/36915)
- refactor(ui): move the model hub and model select onto shadcn primitives by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36918](https://github.com/BerriAI/litellm/pull/36918)
- fix(ui): keep the cost tracking removal confirmation open until it settles by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36960](https://github.com/BerriAI/litellm/pull/36960)
- refactor(ui): declare DateRangePickerValue locally instead of importing it from tremor by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36962](https://github.com/BerriAI/litellm/pull/36962)
- fix(main): an explicit provider outranks a known OpenAI model name by [@​FahimaGold](https://github.com/FahimaGold) in [#​36800](https://github.com/BerriAI/litellm/pull/36800)
- fix(exception\_mapping): bare 429 in an error body no longer outranks the status code by [@​FahimaGold](https://github.com/FahimaGold) in [#​36705](https://github.com/BerriAI/litellm/pull/36705)
- refactor(ui): move MCP permission panels onto shadcn primitives by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36964](https://github.com/BerriAI/litellm/pull/36964)
- refactor(ui): migrate ten small dashboard files off antd and tremor by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36966](https://github.com/BerriAI/litellm/pull/36966)
- fix(proxy): force prisma recreate on postgres cached-plan error by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36428](https://github.com/BerriAI/litellm/pull/36428)
- fix(transcription): stop a zero output rate from zeroing transcription cost by [@​hMED22](https://github.com/hMED22) in [#​36914](https://github.com/BerriAI/litellm/pull/36914)
- fix(langfuse): restrict trace steering keys to real langfuse trace fields by [@​yucheng-berri](https://github.com/yucheng-berri) in [#​36862](https://github.com/BerriAI/litellm/pull/36862)
- Revert "fix(auth): stop the team fallback from widening model access" ([#​36837](https://github.com/BerriAI/litellm/issues/36837)) by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36982](https://github.com/BerriAI/litellm/pull/36982)
- fix(ui): show zeroed auto-router usage stats when a window has no sessions by [@​tin-berri](https://github.com/tin-berri) in [#​36868](https://github.com/BerriAI/litellm/pull/36868)
- fix(mcp): keep admin-entered oauth endpoints in management reads by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36888](https://github.com/BerriAI/litellm/pull/36888)
- fix(ui): distinguish hosted and local vLLM in the provider dropdown by [@​mateo-berri](https://github.com/mateo-berri) in [#​36974](https://github.com/BerriAI/litellm/pull/36974)
- fix(openai,azure): return a length-truncated 200 when the output budget fits no token by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36859](https://github.com/BerriAI/litellm/pull/36859)
- fix(proxy): always emit the Anthropic /v1/models token limits, null when unknown by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36961](https://github.com/BerriAI/litellm/pull/36961)
- feat(helm): add startupProbe and hpa.behavior to the componentized chart by [@​Louis-Vauterin](https://github.com/Louis-Vauterin) in [#​36382](https://github.com/BerriAI/litellm/pull/36382)
- fix(proxy): serve aggregate MCP endpoint on bare /mcp instead of 307-redirecting by [@​tin-berri](https://github.com/tin-berri) in [#​34845](https://github.com/BerriAI/litellm/pull/34845)
- feat(shadow\_eval): add reverse-direction shadow eval jobs by [@​tin-berri](https://github.com/tin-berri) in [#​36865](https://github.com/BerriAI/litellm/pull/36865)
- fix(proxy): requeue Redis spend buffer transactions when the DB commit fails by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​33881](https://github.com/BerriAI/litellm/pull/33881)
- feat(search): add Nimble as a search provider by [@​ilchemla](https://github.com/ilchemla) in [#​36347](https://github.com/BerriAI/litellm/pull/36347)
- fix(mcp): drop caller host and configured upstream headers from logged metadata by [@​yucheng-berri](https://github.com/yucheng-berri) in [#​36901](https://github.com/BerriAI/litellm/pull/36901)
- fix(azure\_ai): recognize real Search doc endpoints so teams can read/write via passthrough by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36798](https://github.com/BerriAI/litellm/pull/36798)
- fix(anthropic): aggregate 5m/1h cache-write split across iterations path by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​34860](https://github.com/BerriAI/litellm/pull/34860)
- fix(anthropic cost): apply regional geo uplift to cached tokens by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​34850](https://github.com/BerriAI/litellm/pull/34850)
- fix(ui): match the MCP servers count badge to its sibling permission badges by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36984](https://github.com/BerriAI/litellm/pull/36984)
- fix(batches): mark terminal batch with no output file as processed in CheckBatchCost by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​35360](https://github.com/BerriAI/litellm/pull/35360)
- fix(caching): cache anthropic /v1/messages responses, including streaming by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​34581](https://github.com/BerriAI/litellm/pull/34581)
- fix(anthropic\_messages): make tool\_result images visible to OpenAI-compatible providers by [@​hMED22](https://github.com/hMED22) in [#​34462](https://github.com/BerriAI/litellm/pull/34462)
- feat(fireworks\_ai): translate NIM/vLLM extra params to Fireworks-native args by [@​milesadkins](https://github.com/milesadkins) in [#​35969](https://github.com/BerriAI/litellm/pull/35969)
- fix(ui): stop the models tab strip from scrolling vertically by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36993](https://github.com/BerriAI/litellm/pull/36993)
- fix(ui): anchor chips-combobox popups to the field instead of the inner input by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36995](https://github.com/BerriAI/litellm/pull/36995)
- feat(proxy): per-component response cost headers by [@​erensh27](https://github.com/erensh27) in [#​36965](https://github.com/BerriAI/litellm/pull/36965)
- fix(cost): track OpenAI/Azure web search tool cost per call by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​35286](https://github.com/BerriAI/litellm/pull/35286)
- fix(bedrock): resolve aliases in batch file records by [@​daleselaji-dev](https://github.com/daleselaji-dev) in [#​36159](https://github.com/BerriAI/litellm/pull/36159)
- fix: report real token usage on guardrail-blocked /v1/responses replies by [@​guptaishaan](https://github.com/guptaishaan) in [#​36907](https://github.com/BerriAI/litellm/pull/36907)
- fix(proxy): requeue spend logs when the DB write fails with a transport error by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36716](https://github.com/BerriAI/litellm/pull/36716)
- fix(cost): tiered pricing supports cache creation cost and is all-or-nothing by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36720](https://github.com/BerriAI/litellm/pull/36720)
- fix(vertex\_ai): translate /v1/embeddings batch rows to the Gemini embedding shape by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​35092](https://github.com/BerriAI/litellm/pull/35092)
- docs(claude): require ReadOnly on every TypedDict field (LIT012) by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​37005](https://github.com/BerriAI/litellm/pull/37005)
- refactor(ui): migrate access group create modal to RHF + zod + shadcn by [@​ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#​37033](https://github.com/BerriAI/litellm/pull/37033)
- refactor(ui): re-sync badge and skeleton onto the base-vega shadcn style by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36991](https://github.com/BerriAI/litellm/pull/36991)
- feat(ui): link user detail team names to team pages by [@​ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#​37022](https://github.com/BerriAI/litellm/pull/37022)
- fix(model\_prices): correct DeepSeek V4 max output tokens by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36925](https://github.com/BerriAI/litellm/pull/36925)
- fix(ui): rename models table Status column to Source by [@​ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#​37021](https://github.com/BerriAI/litellm/pull/37021)
- chore: bump litellm-enterprise 0.1.55 -> 0.1.56, litellm-proxy-extras 0.4.85 -> 0.4.86 by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​37045](https://github.com/BerriAI/litellm/pull/37045)
- feat(proxy): gate the Global Control Plane worker registry on an enterprise license by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​36996](https://github.com/BerriAI/litellm/pull/36996)
- fix(model\_prices): add gemini 3.1 flash tts preview and legacy OpenAI shutdown dates by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36788](https://github.com/BerriAI/litellm/pull/36788)
- fix(panw\_prisma\_airs): surface scan\_id on allowed requests by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​37037](https://github.com/BerriAI/litellm/pull/37037)
- fix(model\_map): flag native structured outputs on Anthropic-direct claude-sonnet-5 and claude-haiku-4-5 by [@​anmolg1997](https://github.com/anmolg1997) in [#​35930](https://github.com/BerriAI/litellm/pull/35930)
- fix(router): stop get\_router\_model\_info from wiping cached pricing by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36985](https://github.com/BerriAI/litellm/pull/36985)
- fix(redis): unwrap decorated \_\_init\_\_s when deriving the from\_url kwargs allowlist by [@​anmolg1997](https://github.com/anmolg1997) in [#​36654](https://github.com/BerriAI/litellm/pull/36654)
- fix(proxy): reserve the larger declared output budget for TPM limits by [@​yassin-berriai](https://github.com/yassin-berriai) in [#​37001](https://github.com/BerriAI/litellm/pull/37001)
- fix(databricks): surface provider usage, including prompt-cache counts, in streaming chunks by [@​pokepoke81](https://github.com/pokepoke81) in [#​36943](https://github.com/BerriAI/litellm/pull/36943)
- fix(spend): give a batch's cost row a primary key of its own by [@​marty-sullivan](https://github.com/marty-sullivan) in [#​36876](https://github.com/BerriAI/litellm/pull/36876)
- feat: shadow eval samples /v1/messages and /v1/responses traffic by [@​tin-berri](https://github.com/tin-berri) in [#​36830](https://github.com/BerriAI/litellm/pull/36830)
- fix(ptu): stop a PTU deployment billing for grounded search by [@​yucheng-berri](https://github.com/yucheng-berri) in [#​37043](https://github.com/BerriAI/litellm/pull/37043)
- fix(fireworks\_ai): support router slugs via routers/ prefix by [@​heathriel](https://github.com/heathriel) in [#​34257](https://github.com/BerriAI/litellm/pull/34257)
- fix(bedrock): register managed-batch litellm\_params so they stop leaking to the provider (internal copy of [#​36633](https://github.com/BerriAI/litellm/issues/36633)) by [@​mateo-berri](https://github.com/mateo-berri) in [#​37048](https://github.com/BerriAI/litellm/pull/37048)
- fix(bedrock): resolve the managed-batch output bucket on every path that reads it by [@​mateo-berri](https://github.com/mateo-berri) in [#​37047](https://github.com/BerriAI/litellm/pull/37047)
- fix(bedrock): resolve the managed-batch output bucket on every path that reads it by [@​marty-sullivan](https://github.com/marty-sullivan) in [#​36634](https://github.com/BerriAI/litellm/pull/36634)
- feat(scripts): queue heavy gates behind a machine-wide slot lock by [@​mateo-berri](https://github.com/mateo-berri) in [#​36988](https://github.com/BerriAI/litellm/pull/36988)
- feat(mcp): scope gateway session bearers to the RFC 8707 resource by [@​tin-berri](https://github.com/tin-berri) in [#​35045](https://github.com/BerriAI/litellm/pull/35045)
- feat(ui): direction picker and reverse-mode display for shadow evals by [@​tin-berri](https://github.com/tin-berri) in [#​36994](https://github.com/BerriAI/litellm/pull/36994)
- fix(guardrails): return the full PANW AIRS scan response on blocked requests by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​37036](https://github.com/BerriAI/litellm/pull/37036)
- fix(passthrough): stop forwarding client Accept-Encoding upstream by [@​mateo-berri](https://github.com/mateo-berri) in [#​37058](https://github.com/BerriAI/litellm/pull/37058)
- fix(batches): account a managed batch's cost exactly once by [@​mateo-berri](https://github.com/mateo-berri) in [#​37050](https://github.com/BerriAI/litellm/pull/37050)
- fix(panw\_prisma\_airs): scan tool call args as plain text, not a tool\_event by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​37038](https://github.com/BerriAI/litellm/pull/37038)
- feat(lint): exempt TypedDict-annotated dict literals from LIT002 by [@​mateo-berri](https://github.com/mateo-berri) in [#​36869](https://github.com/BerriAI/litellm/pull/36869)
- docs(claude): tell agents to let heavy gates queue for machine-wide slots by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​37057](https://github.com/BerriAI/litellm/pull/37057)
- test: unstick the suites CircleCI is failing on by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​37059](https://github.com/BerriAI/litellm/pull/37059)
- docs(github): proof-of-fix section shows only the latest run as Before/After with nested cases by [@​mateo-berri](https://github.com/mateo-berri) in [#​37063](https://github.com/BerriAI/litellm/pull/37063)
- test(e2e): assert provider error shape instead of pinned prose by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​37065](https://github.com/BerriAI/litellm/pull/37065)
- fix(ui): de-duplicate the reset budget option and polish shadcn surfaces by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​37010](https://github.com/BerriAI/litellm/pull/37010)
- chore: rebuild Admin UI bundle from litellm\_internal\_staging by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​37066](https://github.com/BerriAI/litellm/pull/37066)
- test(e2e/ui): assert the log drawer chevrons by their lucide classes by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​37069](https://github.com/BerriAI/litellm/pull/37069)
- chore(ci): promote internal staging to main by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​37042](https://github.com/BerriAI/litellm/pull/37042)
- fix(ui): keep completion-mode models in the playground chat dropdown (backport to rc/1.98.0) by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​37955](https://github.com/BerriAI/litellm/pull/37955)
##### New Contributors
- [@​kr0k](https://github.com/kr0k) made their first contribution in [#​33196](https://github.com/BerriAI/litellm/pull/33196)
- [@​HuanQian571](https://github.com/HuanQian571) made their first contribution in [#​35773](https://github.com/BerriAI/litellm/pull/35773)
- [@​alexshtf](https://github.com/alexshtf) made their first contribution in [#​35669](https://github.com/BerriAI/litellm/pull/35669)
- [@​vairodp](https://github.com/vairodp) made their first contribution in [#​33490](https://github.com/BerriAI/litellm/pull/33490)
- [@​fancybear-dev](https://github.com/fancybear-dev) made their first contribution in [#​36196](https://github.com/BerriAI/litellm/pull/36196)
- [@​daleselaji-dev](https://github.com/daleselaji-dev) made their first contribution in [#​36160](https://github.com/BerriAI/litellm/pull/36160)
- [@​eugene-yao-zocdoc](https://github.com/eugene-yao-zocdoc) made their first contribution in [#​34290](https://github.com/BerriAI/litellm/pull/34290)
- [@​geraint0923](https://github.com/geraint0923) made their first contribution in [#​30817](https://github.com/BerriAI/litellm/pull/30817)
- [@​william-xue](https://github.com/william-xue) made their first contribution in [#​36529](https://github.com/BerriAI/litellm/pull/36529)
- [@​dcadenas](https://github.com/dcadenas) made their first contribution in [#​32536](https://github.com/BerriAI/litellm/pull/32536)
- [@​atomic](https://github.com/atomic) made their first contribution in [#​34177](https://github.com/BerriAI/litellm/pull/34177)
- [@​Praveen11558](https://github.com/Praveen11558) made their first contribution in [#​30952](https://github.com/BerriAI/litellm/pull/30952)
- [@​anxkhn](https://github.com/anxkhn) made their first contribution in [#​32813](https://github.com/BerriAI/litellm/pull/32813)
- [@​lostmartian](https://github.com/lostmartian) made their first contribution in [#​36660](https://github.com/BerriAI/litellm/pull/36660)
- [@​FahimaGold](https://github.com/FahimaGold) made their first contribution in [#​36800](https://github.com/BerriAI/litellm/pull/36800)
- [@​Louis-Vauterin](https://github.com/Louis-Vauterin) made their first contribution in [#​36382](https://github.com/BerriAI/litellm/pull/36382)
- [@​ilchemla](https://github.com/ilchemla) made their first contribution in [#​36347](https://github.com/BerriAI/litellm/pull/36347)
- [@​milesadkins](https://github.com/milesadkins) made their first contribution in [#​35969](https://github.com/BerriAI/litellm/pull/35969)
- [@​erensh27](https://github.com/erensh27) made their first contribution in [#​36965](https://github.com/BerriAI/litellm/pull/36965)
- [@​guptaishaan](https://github.com/guptaishaan) made their first contribution in [#​36907](https://github.com/BerriAI/litellm/pull/36907)
- [@​pokepoke81](https://github.com/pokepoke81) made their first contribution in [#​36943](https://github.com/BerriAI/litellm/pull/36943)
- [@​heathriel](https://github.com/heathriel) made their first contribution in [#​34257](https://github.com/BerriAI/litellm/pull/34257)
**Full Changelog**: <https://github.com/BerriAI/litellm/compare/v1.97.0...v1.98.0>
### [`v1.98.0`](https://github.com/BerriAI/litellm/releases/tag/v1.98.0)
[Compare Source](https://github.com/BerriAI/litellm/compare/v1.97.0...v1.98.0)
##### Verify Docker Image Signature
All LiteLLM Docker images are signed with [cosign](https://docs.sigstore.dev/cosign/overview/). Every release is signed with the same key introduced in [commit `0112e53`](https://github.com/BerriAI/litellm/commit/0112e53046018d726492c814b3644b7d376029d0).
**Verify using the pinned commit hash (recommended):**
A commit hash is cryptographically immutable, so this is the strongest way to ensure you are using the original signing key:
```bash
cosign verify \
--key https://raw.githubusercontent.com/BerriAI/litellm/0112e53046018d726492c814b3644b7d376029d0/cosign.pub \
ghcr.io/berriai/litellm:v1.98.0
```
**Verify using the release tag (convenience):**
Tags are protected in this repository and resolve to the same key. This option is easier to read but relies on tag protection rules:
```bash
cosign verify \
--key https://raw.githubusercontent.com/BerriAI/litellm/v1.98.0/cosign.pub \
ghcr.io/berriai/litellm:v1.98.0
```
Expected output:
```
The following checks were performed on each of these signatures:
- The cosign claims were validated
- The signatures were verified against the specified public key
```
***
##### What's Changed
- fix(bedrock): drop toolSpec.strict for Claude Sonnet 5 on Converse by [@​kr0k](https://github.com/kr0k) in [#​33196](https://github.com/BerriAI/litellm/pull/33196)
- fix(batches): attribute Vertex passthrough batch cost to key/team/tags by [@​yucheng-berri](https://github.com/yucheng-berri) in [#​34456](https://github.com/BerriAI/litellm/pull/34456)
- docs: rewrite the CLAUDE.md comment rule with explicit exceptions by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36301](https://github.com/BerriAI/litellm/pull/36301)
- fix(proxy): scope file list pagination cursors to the caller by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36093](https://github.com/BerriAI/litellm/pull/36093)
- fix(proxy): skip prisma-dependent hooks when no database is attached by [@​mateo-berri](https://github.com/mateo-berri) in [#​36273](https://github.com/BerriAI/litellm/pull/36273)
- fix(proxy): report has\_more false on caller-scoped file list pages by [@​mateo-berri](https://github.com/mateo-berri) in [#​36326](https://github.com/BerriAI/litellm/pull/36326)
- fix(proxy): restore management\_v1 query-param validation under fastapi>=0.140.7 by [@​HuanQian571](https://github.com/HuanQian571) in [#​35773](https://github.com/BerriAI/litellm/pull/35773)
- fix(proxy): stop /{provider}/v1/files from capturing /openai\_passthrough by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36092](https://github.com/BerriAI/litellm/pull/36092)
- chore(typing): remove 914 basedpyright Any errors across 16 hotspot files by [@​mateo-berri](https://github.com/mateo-berri) in [#​36386](https://github.com/BerriAI/litellm/pull/36386)
- fix(router): keep batch fallbacks inside the model group that owns the file by [@​mateo-berri](https://github.com/mateo-berri) in [#​36181](https://github.com/BerriAI/litellm/pull/36181)
- feat(ptu): configure provisioned-throughput flat cost on a model deployment by [@​yucheng-berri](https://github.com/yucheng-berri) in [#​35341](https://github.com/BerriAI/litellm/pull/35341)
- docs: clarify the CLAUDE.md comment exceptions are any-of by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​36421](https://github.com/BerriAI/litellm/pull/36421)
- docs: replace the Changes …


TLDR
Problem this solves:
How it solves it:
Relevant issues
Linear ticket
Resolves LIT-4077
Pre-Submission checklist
Screenshots / Proof of Fix
Captured live against a proxy on this branch (commit 277f096), real endpoints, no mocks.
Rebased onto litellm_internal_staging at f6587fa on 2026-08-06, which had moved 441 commits past the original branch point. The whole matrix below was re-run against the rebased head on a live proxy and a real Postgres, so nothing here is carried over from the pre-rebase run
The validation matrix, re-run on the rebased head
The stored window comes back as the same UTC wall clock it went in as
Screens
The four fields on the model form, and the cross-field invariant rejecting a half-set pair before it reaches the API:
Per-field bounds, rejected in the form rather than surfacing as a backend error:
This is the first of a stack. The daily rollup that writes ptu_flat_cost, the read path that surfaces it, and the UI land in follow-up PRs
Live run 2026-08-08, commit c0ab5d2
Fresh Postgres, migrations deployed from
litellm-proxy-extras, real Gemini traffic, no mocksThe merged-view fix, driven against a deployment storing count 15 / rate 3.0 / start 2026-08-01
Before this fix the half-clear passed validation on the stored count and committed the team write before
update_db_model's backstop rejected itThe same config as seen by an operator, on Models + Endpoints for the deployment created above
Type
New Feature
Changes
ModelInfo gains ptu_count, cost_per_ptu_per_hour, ptu_effective_from and ptu_effective_to. A model_validator enforces per-field bounds: a positive count, a non-negative rate, and effective_to strictly after effective_from. Bounds run at request-parse time on both model/new and model/{id}/update since both carry a ModelInfo
The cross-field invariant (count and rate set together, team_id required when either is set) is enforced by a helper applied to the effective model_info: on
POST /model/newagainst the create payload, and onPATCH /model/{model_id}/updateagainst the merged stored-plus-incoming model_info, so a partial patch that changes only one field validates the final state rather than the delta. Note the verb:/model/{model_id}/updateis PATCH-only and answers POST with a 405, while the olderPOST /model/updateis a different route that does not write model_info at allThe two invariant failures above answer 400 from the handler. The per-field bounds live on the ModelInfo validator instead, so they are reported at request-parse time as FastAPI's usual 422 rather than 400; both reject the request and persist nothing, but the status codes differ by design and the SDK/Router keep the bounds even when the endpoint is bypassed
The merged view mirrors what the write will store, including the clears.
update_db_modeldrops a PTU field a patch sends as an explicit null, so carrying the stored value into validation approved a deployment that never forms: clearing a count while leaving a rate passed the pair check and then committed the team ACL write before the backstop validator insideupdate_db_modelrejected it. Both paths now derive the cleared set from one helper, so they cannot drift againLiteLLM_DailyTeamSpend gains a ptu_flat_cost column and a sentinel api_key constant, ready for the rollup PR; nothing writes them yet in this PR
Final Attestation
Note
Medium Risk
Requires a DB migration and changes model deployment validation and spend schema; rollup/read paths are not in this PR, so misconfiguration is limited to rejected API payloads until follow-ups land.
Overview
Adds provisioned throughput (PTU) settings on proxy model deployments so flat reservation cost can be configured per team-scoped model before a follow-up rollup writes spend.
ModelInfonow acceptsptu_count,cost_per_ptu_per_hour, and optionalptu_effective_from/ptu_effective_to, with bounds enforced at parse time (positive count, non-negative rate, effective window ordering)./model/newand/model/{id}/update(via mergedmodel_infoinupdate_db_model) call_validate_ptu_model_info: PTU count and hourly rate must be set together, andteam_idis required when either is present.LiteLLM_DailyTeamSpendgainsptu_flat_costandptu_source_model_id(migration + Prisma);PTU_SENTINEL_API_KEYandPTU_ROLLUP_JOB_IDare defined for future rollup rows—nothing writes these columns in this PR. Dashboard OpenAPI types include the new fields.Reviewed by Cursor Bugbot for commit f46ef05. Bugbot is set up for automated code reviews on this repo. Configure here.