chore: sync upstream/main into litellm_internal_staging (2026-08-03, ~372 commits) - #36
Conversation
…ld-039815 chore(ui): rebuild Next.js build artifacts
The shadcn migration carried the antd modal's 1000px width over as an unprefixed max-w-[1000px], which tailwind-merge keeps alongside the DialogContent base class sm:max-w-md; the responsive variant wins from 640px up, so the dialog rendered at 448px. Prefix the override so the merge drops the base clamp
The MCP Servers page was the only page-level tab bar using the segmented (pill) TabsList stretched with w-full, which rendered a full-width grey bar with a lone pill on the left. Every other page-level tab bar (budgets, vector stores, access groups, organizations, routing groups, API reference) uses the underlined line variant, so use that here too.
… body
Vertex passthrough classified any target URL containing "stream" as a streaming
request. `:streamRawPredict` carries that substring, so a unary Claude-on-Vertex
call whose body omits `stream` was routed through the streaming logging path.
That path never consults the response content-type, so a complete
`"type": "message"` JSON body was handed to the Anthropic SSE chunk parser,
which recognises none of it; the spend log recorded 0 prompt tokens,
0 completion tokens and zero cost
Streaming for the rawPredict family now comes from the request body, which is
what the Anthropic Messages contract uses for those endpoints. The
generateContent family keeps its URL signal because the Gemini REST body has no
`stream` field, and `?alt=sse` is still appended for every request that is
classified as streaming, so Gemini framing and its usage parsing are unchanged
Both passthrough streaming predicates read `.get("stream")` off a body that is
only annotated as a dict; `_read_request_body` returns whatever the JSON parser
produced, so an array body raised AttributeError. The two predicates are now one
owner that answers False for any non-object body, which covers the vertex,
mistral, anthropic, vllm and azure passthrough routes
…_context fix(azure_ai): advertise 1M context window for Claude Opus 4.6+ on Foundry
…e button DialogContent's close button is absolutely positioned 16px from the right edge at 32px wide, so it overlays the rightmost 24px of the p-6 content box. The justify-between header pins "+ Custom Server" to that same edge and, being out of flow, the close button reserves nothing. Give the action a right margin that clears it; keeping the margin on the button rather than the row leaves the header rule full-bleed
The shadcn separator primitive ships `data-vertical:self-stretch` so a bare vertical divider fills its row, but every call site overrides the height with `h-5`. A definite cross size makes `align-self: stretch` behave as `flex-start`, so the dividers rendered flush with the top of their flex line instead of centered: 0px above and 18px below in the dashboard header, 0px above and 12px below in the models table toolbar Routes the three vertical dividers through a ToolbarSeparator that pairs the fixed height with a same-variant `data-vertical:self-center`. Matching the variant is what matters; tailwind-merge then drops the conflicting class outright, whereas a plain `self-center` ties on specificity (the variant is defined with `:where()`) and loses on utility order. The CLI-managed primitive is left untouched
…m_resource feat(mcp): send RFC 8707 resource indicators on upstream OAuth legs
…up in llm_as_a_judge (BerriAI#34509) * fix(guardrails): resolve judge_model credentials via Router in llm_as_a_judge Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix(guardrails): wire llm_router into DB-backed judge guardrail init paths Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(guardrails): assert patch endpoint forwards llm_router to sync Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * refactor(guardrails): resolve judge Router lazily and fix wildcard/alias dispatch Resolve the proxy Router at judge-call time via an injected provider instead of capturing it at construction, so a DB-backed judge guardrail created before the Router exists no longer captures None permanently. Select the Router path with router.get_model_list(model_name=judge_model) so wildcard routes and model_group_alias keys resolve, not just literal deployment names. Isolate the judge call from user-traffic routing with num_retries=0 and fallbacks=[]. Revert the llm_router threading through the DB sync/reinit/create/approve/patch paths since the lazy provider makes it unnecessary. Replace mocked-Router tests with real Router coverage for plain deployments, model_group_alias, and wildcard routes, plus lazy per-call resolution. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix(guardrails): harden judge verdict parsing and guard proxy import Strip markdown fences and surrounding prose before json.loads so fencing-prone judge models evaluate instead of failing open, guard the proxy_server import in _default_router_provider so an unimportable proxy falls back to the SDK, and snapshot/restore global callback lists in the DB-path judge registry tests Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix(guardrails): reject non-object judge verdicts instead of failing open as success * fix(guardrails): route hidden model_group_alias judge models through the Router --------- Co-authored-by: milan <milan@berri.ai> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: yucheng-berri <yucheng@berri.ai>
GET /v1/tool/spend served the Cost Optimization card with two raw queries
over LiteLLM_SpendLogToolIndex x LiteLLM_SpendLogs on every dashboard load;
the totals query's driving scan was all of SpendLogs in the window. Both
per-request tables reach 1M+ rows at customer scale, so the card cost
O(traffic) per view and had to be capped at 30 days.
The index writer also mined proxy_server_request.tools, i.e. tools DECLARED
in the request body, attributing each request's full spend to tools that
never ran; and all non-MCP mining ran against payload fields that are '{}'
unless store_prompts_in_spend_logs is enabled, so non-MCP coverage silently
depended on a privacy setting.
Now the spend writer builds a ToolUsageTransaction at request time from
invoked tools only, resolved by the shared get_tool_calls_from_response
normalizer so every response surface (chat completions, Responses API,
Anthropic Messages) is covered; the tool registry's response arm delegates
to the same owner. Transactions queue beside the spend-log queue and the
flush job writes index rows plus a new LiteLLM_DailyToolSpend rollup
(date, tool_name PK) in one transaction, retrying connection errors with
backoff (a failed batch commits nothing, so the retry cannot double-count)
and dropping the batch with an error log on anything else.
The endpoint aggregates in SQL: by_tool is the top TOOL_SPEND_TOP_TOOLS
tools by spend via group_by and daily covers only those tools, so the
response is bounded by days x TOOL_SPEND_TOP_TOOLS regardless of range or
tool-name cardinality; the 30-day clamp is gone. total_spend is dropped
from the response; it was never rendered and its deduplicated semantics
are not computable from a rollup. Spend-log retention deliberately does
not touch the rollup, so tool spend history outlives per-request rows.
…itellm_/model-table-divider-center-b75b6d
…itellm_/mcp-tabs-styling-dd340c
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The Team dropdown popup is pinned to the trigger width via w-(--anchor-width) and clips its overflow, while Base UI's ItemText wrapper is flex-1 shrink-0 with min-width: auto, so it sizes itself to the full nowrap label and simply overflows the popup. Teams without a team_alias render their 36-char id, so those options were sliced mid-character with no ellipsis. Clears min-width: auto off the text wrapper and truncates the label at the call site. The underlying gap is in the shared Select primitive, which any long-labelled select in the dashboard will hit; that is left for a separate change.
…pdown-truncate-2b2a3f
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
`/customer/aliases` shipped two days ago and has not been in a release, so its
wire contract is still free to change. This lands it on the control-plane
contract before that stops being true, since after a release the path, the param
names and the envelope would all need a permanent legacy adapter
The endpoint becomes `GET /management/v1/spend_logs/end_users`. It is a facet,
the distinct values one column takes over a filtered query on a resource, not an
entity collection; naming it after `customers` implied it listed the end-user
table when it actually reads spend logs, which is a different row set. Serving it
under the parent resource means its filters are the parent's filters, so the
dropdown offers exactly the values the logs table can show without two endpoints
having to keep agreeing on that
Contract changes: `size` becomes `page_size`, `search` becomes `q`, the window
moves from flat `start_date` / `end_date` to `filter[startTime][gte]` / `[lte]`,
and the body becomes `{data, meta, links}`. Unknown query params are now a 400
rather than being silently dropped, because an ignored filter over-returns data.
Errors are RFC 9457 problem documents on this prefix only; every other route
keeps the shape its callers already parse
`links` is what makes the rest deferrable. The dashboard hook follows the
server's `links.next` instead of computing `page + 1`, so moving this to cursor
pagination later changes the links and nothing the client does. That matters
because the inner scan is a sliding window, so offset paging can currently skip
or repeat an end user across pages; the fix is a follow-up, and the hypermedia
means it will not be a breaking one
Cursor mode, `sort`, `include`, ETag / `If-None-Match` and the generic `ListSpec`
framework are all deliberately out of scope here. They are additive or internal,
so none of them needs to beat the release
…oint-standards-b1cd57
The RFC 9457 `type` was `https://docs.litellm.ai/errors/<slug>`, copied from the standard's own error example. That path is a 404 and there is no docs section behind it, so every error body shipped a broken link RFC 9457 only requires `type` to identify the problem type; it encourages, but does not require, that dereferencing it yield documentation. An https URI makes a promise we are not keeping, so use `urn:litellm:error:<slug>` instead, which carries the same machine-readable identity with nothing to resolve. Switching to an https base later is a contract change for anyone matching on `type`, so that should wait for pages that actually exist A test pins the identifier against regressing to an https docs URL, since the existing assertion built the expected value from the same constant and would have stayed green whatever it held
…ollup Three fixes from an adversarial review of this branch, each at the owning seam rather than the report site. The flush retried DB_CONNECTION_ERROR_TYPES, which includes ReadTimeout. A ReadTimeout is the committed-but-unacked case: the review reproduced the engine abandoning the transaction open on the pooled connection, the retry stacking its statements into it, and one commit applying both increment sets while the flush reports success. The retry now covers only ConnectError, the one failure that proves the statements never reached the database; post-send failures drop the batch with an error log. The docstring no longer claims an idempotency the pattern does not have. The same hazard exists in the untouched daily spend writer and is left for its own change. get_tool_calls_from_response read choices[0] only, so a tool invoked in a later choice of an n>1 response earned spend but never reached the rollup, the index, or the registry. Choice scope is now an explicit parameter: accounting passes include_all_choices=True because every choice costs money; guardrails keep the primary-choice default because they rebuild the primary assistant message. First multi-choice fixtures in the suite pin both scopes. maxBarSize=64 had been added to the shared BarChart unconditionally, resizing every existing consumer. It is now a prop; only the tool spend charts opt in. The legend flex-wrap changes stay global because clipping overflow was a defect, not a preference.
…iles Replace Any-typed seams with real types in the files carrying the highest reportAny/reportExplicitAny density: typed Prisma read helpers in the MCP db layer and verification token repository, TypedDicts for OAuth credential payloads and aggregated spend rows, a DailySpendRecord protocol for the daily activity endpoints, and concrete request/response types in the volcengine, openai evals, azure batches, azure_ai count_tokens, and ocr transformation modules. Modernize touched annotations to PEP 604/585 forms. No casts, no type: ignore, no noqa, no new Any annotations, no behavior changes. Whole-tree basedpyright: reportAny 27,005 -> 24,427, reportExplicitAny 7,439 -> 7,280, no rule increased anywhere. Budgets ratcheted: basedpyright -2,869, ruff-strict -1,505, type-discipline -167.
uv selects an interpreter before resolving dependencies, so with no --python request the stock macOS /usr/bin/python3 (3.9.6) satisfies the unconstrained request and resolution then fails against litellm's requires-python (>=3.10,<3.15) instead of downloading a managed Python. Request the requires-python range explicitly in install-cli.sh and install.sh so uv reuses a compatible system interpreter when present and downloads a managed one otherwise. The manual-fallback hint in the die message carries the same flag so it no longer reproduces the failure.
Both failures are from this branch, not pre-existing The component allowlist test asserts the gateway and backend route sets union to the whole app, so any route on neither is a 404 on both pods. Allowlist the `/management/v1/` prefix on the backend, next to the other control plane entries, so every resource that moves under it later is covered without a per-resource edit The otel handler test builds its request as a SimpleNamespace carrying only `state`. The validation handler now reads `request.url.path` to decide whether the caller is on a surface with its own error contract, so the fake needs a url; a real Request always has one, which is why the handler does not guard for it The control plane branch returns early, and nothing covered that it still closes the dangling SERVER span first, so those requests would have leaked a span apiece. Added a case that pins it; removing the close call fails it
…ng-dd340c style(ui): match MCP Servers tabs to the dashboard's line tab pattern
…vider-center-b75b6d fix(ui): center vertical toolbar dividers
…toration-c06977 fix(ui): restore the Add MCP Server dialog size and header spacing
…opdown-truncate-2b2a3f fix(ui): truncate long team names in the models table team dropdown
Same cause as the otel handler test: this file builds its request as a SimpleNamespace carrying only `state`, and the validation handler now reads `request.url.path` to pick an error contract, so the fake needs a url While here, cover what the two existing tests do not. They only exercise the proxy-wide 422, and the control plane's 400 problem document was reachable only through the route test, which registers its own copy of the handler in a local app rather than the real one. Two cases now pin the real handler directly: a `/management/v1` path returns problem+json with a `detail` string, and paths that merely resemble the prefix (`/management`, `/v1/management/foo`) keep the 422 shape their callers parse
…n classifier call (BerriAI#35300) The complexity router's classifier sub-call copies the parent request's metadata verbatim, so its spend log row carries the caller's key, team and user and is indistinguishable from traffic the caller actually sent. Nothing on the row says otherwise: call_type is "acompletion" either way, model_group is overwritten to the classifier's own model group so the row never looks auto-routed, and routing_decision is absent exactly as it is on an ordinary request. Record the fact the system already knows at call time. internal_call_origin is declared on SpendLogsMetadata, which is the allowlist _get_spend_logs_metadata projects onto, and stamped in _classifier_call_metadata; both classifier paths already route through that one function and it feeds the metadata and litellm_metadata buckets alike, so every request surface is covered at one site. The key is reserved rather than caller-supplied, so it joins routing_decision in the untrusted-metadata strip and a caller cannot label their own traffic as router overhead. The classifier call also inherited no session identity, so the router minted a fresh trace id and the row landed in a session of its own. Forwarding the parent's session puts it in the trace of the request that triggered it, which is where an operator looks for what the routing cost.
…hen all DB versions are deleted
…s_guardrail_info fix(logging): bind litellm_metadata by reference in function_setup so guardrail info reaches spend logs
… order-dependent flake
…erriAI#35291) * feat(s3): support SSE-KMS encryption params on both S3 logging paths * fix(s3): ignore non-string SSE config values instead of crashing logger init * Update litellm/integrations/s3.py Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix(s3): invalidate only the mistyped SSE field instead of dropping both --------- Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…_survive_db_sync fix(policy_engine): preserve config-defined policies across DB sync and expose them via list APIs
…_guardrail_flake test: fix order-dependent flake in passthrough guardrail call-type test
…itellm_responses_error_code_map
fix(pricing): correct gpt-5.6 prices for openai, bedrock, and flex long context
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ice_tier fix(cost): bill the fast service tier at the priority rate
…_code_map fix(responses): map all documented in-stream error codes to real HTTP statuses
…est_gaps test(pricing): cover gpt-5.6 cache-cost plumbing and bedrock_mantle responses billing
chore: promote staging to main
… ~372 commits) Weekly-cadence sync following the v1.93.0 and 2026-07-28 precedents. Conflicts (7): - test_server_root_path.yml: deleted upstream, deletion taken (supersedes our #28 Node unpin for a workflow that no longer exists) - test-model-map.yaml: semantic union — our backup-map validation + duplicate-key check retained, upstream's schema sync check added - ui package.json/lock, uv.lock: upstream taken (upstream postcss 8.5.22 supersedes our 8.5.18 security floor) - ruff/type-discipline budgets: max-union placeholder; regenerated to the merged tree's actual counts in the follow-up commit
The fleet brain since NOL-376. Neither upstream branch prices the dated OpenRouter slug, so proxy spend depended entirely on the litellm-config model_info pin; with the key in the map the pricing is defense-in-depth. Added to canonical and backup byte-identical (the #29 lesson: the two maps drift and only one is live in any given deployment). OpenRouter list 2026-08-03: $0.09/M in, $0.18/M out, $0.018/M cache read.
make lint-ruff-budget-update / lint-type-discipline-budget-update over the post-sync tree, replacing the merge's max-union placeholders with actual counts (both sides had ratcheted independently since the last sync).
Base moved four commits ahead (MiniMax video/image providers #31, the blind-catch narrowing #33, and the two Gemini Veo route fixes #34/#35). Everything auto-merged except tests/test_litellm/interactions/test_openapi_compliance.py, where both sides had independently loosened the same Content-discriminator assertion after Google's spec dropped the keyword: base via #31, upstream via BerriAI#35161. Kept upstream's version, which is a strict superset (it accepts a discriminator mapping *or* a per-variant `type` const/1-item enum, asserts the values are distinct, and pins TextContent to "text") and matches the `_declared_type_value` helper already in the file. Budget ceilings: LIT002 (27511 -> 27678) and TRY004 (98 -> 100) were the only two rules over limit on the merged tree with a count above the base, so the gates would have failed. The merge adds no net-new violations: every file's LIT002 count in the merged tree equals one of its two parents, so the overage is purely the union of ceilings both sides had ratcheted down independently since the branch point. Raised those two to the merged tree's actual counts; every other ratchet is untouched. Also regenerated model_prices_and_context_window.schema.json, which the new upstream sync check flagged as stale (missing `output_cost_per_audio`) already before this merge. Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
|
Found 1 test failure on Blacksmith runners: Failure
|
…ed budgets Three reds on the sync branch, all CI/infra rather than product code. test-model-map's schema-sync step runs `uv run --frozen`, which installs the project and therefore builds the litellm-rust bridge through maturin. The locked aws-sdk/aws-smithy crates need rustc 1.94.1 and the runner image preinstalls 1.92.0, so cargo failed before the check ever ran. The repo already has a composite action for exactly this (12 other workflows use it); this job was missing it because neither the fork's nor upstream's copy of the workflow had a Rust step before upstream added the uv-based check. OSV flagged two advisories against the merged UI lock: postcss 8.5.22 (GHSA-fxqj-rqcc-2cmp) and brace-expansion 5.0.8 (GHSA-rgw5-rvv9-x895, dev). Both are patch bumps to 8.5.23 / 5.0.9, applied to the devDependency pin and the security overrides so the floors stay explicit. Regenerating the lock also pruned three stale @playwright/test optional-peer entries; nothing in the dashboard's package.json, workflows, or vitest config references playwright. Budget ceilings: the previous commit cleared the two gate breaches but left the merge's max-union values in place, which loosened 14 limits. Recomputed each as the tightest value that still passes the gate (the stricter of the two sides, raised to the merged tree's actual count only when that count also exceeds the base's count). That recovers base's stricter ratchet on 9 rules and leaves 5 unavoidable raises: BLE001 +1, DTZ005 230->233, I001 267->270, TRY004 98->100, LIT002 27511->27678. The non-gating budget-ratchet job stays red on those by design so a human acknowledges them; removing them would mean editing upstream code this sync is only carrying. Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a3f35a1bed
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| @@ -31072,6 +31078,21 @@ | |||
| "supports_reasoning": true, | |||
| "supports_tool_choice": true | |||
| }, | |||
| "openrouter/deepseek/deepseek-v4-flash-0731": { | |||
| "input_cost_per_token": 9e-08, | |||
| "input_cost_per_token_cache_hit": 1.8e-08, | |||
There was a problem hiding this comment.
Use the cache-read pricing key
When OpenRouter reports cached prompt tokens for this model, the generic cost path reads cache_read_input_token_cost and multiplies cached tokens by that value; input_cost_per_token_cache_hit is never consumed by the cost calculator. Consequently this entry—and its identical backup-map entry—prices cache hits at zero instead of the intended $0.018/M, undercounting spend whenever the deployment relies on the packaged map. Store the rate as cache_read_input_token_cost and cover cached-token cost calculation for this model.
AGENTS.md reference: AGENTS.md:L15-L15
Useful? React with 👍 / 👎.
|
|
||
| if in_response_to is not None: | ||
| authn_key = f"{_SAML_AUTHN_REQUEST_CACHE_PREFIX}:{in_response_to}" | ||
| if cache.get_cache(key=authn_key) is None: |
There was a problem hiding this comment.
Share SAML request state across workers
In a multi-worker or multi-pod deployment where enable_redis_auth_cache remains at its default false, the SAML login request ID is stored only in the initiating worker's in-memory user_api_key_cache; this remains true even when a coordination Redis is configured. If the IdP callback lands on another worker, this lookup misses and rejects an otherwise valid SP-initiated login with 401, making admin login fail intermittently behind a normal load balancer. Store SAML request and replay state in an always-shared cache when Redis is available, or explicitly require sticky sessions/shared state for SAML.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
saml_sso.py is entirely upstream code (upstream PR BerriAI#31429), not introduced or modified by this sync PR. Reworking upstream's brand-new SAML request-state storage would create fork divergence in a security-sensitive file upstream is actively developing; it should be fixed upstream.
| ProxyStartupEvent._add_proxy_budget_to_db() | ||
| asyncio.create_task( | ||
| ProxyStartupEvent._warm_global_spend_cache( |
There was a problem hiding this comment.
Finish proxy-budget initialization before warming spend
When an existing litellm-proxy-budget row has lifetime spend and a null budget_reset_at, startup launches the upsert/backfill and cache warm-up as separate tasks. The warm-up can read and cache the old spend while _upsert_proxy_budget_with_reset_at_backfill is awaiting its DB writes, after which the backfill zeroes the row without invalidating the value just cached. The proxy can then reject requests against stale pre-window spend until the cache expires; await the upsert/backfill before warming the global spend cache, or invalidate the cache after the backfill.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
The _add_proxy_budget_to_db() / _warm_global_spend_cache task pair is upstream code (blame: upstream commits from 2026-01-29 and 2026-07-25), untouched by this fork. Reordering upstream's startup sequence is out of scope for a sync PR and belongs upstream.
…eads `openrouter/deepseek/deepseek-v4-flash-0731` carried its $0.018/M cache-read rate only as `input_cost_per_token_cache_hit`. ModelInfoBase declares that field but no cost calculator reads it: `_calculate_input_cost` bills cached prompt tokens at `cache_read_input_token_cost`, which `_get_token_base_cost` resolves to 0.0 when absent. So cache hits billed at $0 rather than $0.018/M, undercounting spend on the fleet brain, and prod feels it because it runs LITELLM_LOCAL_MODEL_COST_MAP=True and bills off the packaged backup map. Added `cache_read_input_token_cost` at the same rate to both maps, keeping the cache_hit spelling as the 23 other dual-key entries (deepseek/deepseek-chat and the novita family) already do. Covered the billing through the local map so a regression shows up as the money it costs, plus a map-shape pin next to the other canonical/backup drift guards. Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
Upstream BerriAI#34885 wrapped the Tabs props at printWidth 100, but this fork's ui/litellm-dashboard/.prettierrc sets printWidth 120, so `prettier --check` in the gating UI Lint job rejected the file. Whitespace only, produced by the pinned prettier 3.2.5. Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
|
budget-ratchet acknowledgment (merging over the red per the check's own contract). The five raises are all violations inherited from upstream code in this ~372-commit sync, not new fork code:
The check states: "This check is non-gating: if the increase is justified (e.g. a newly banned API), a human can merge over the red after acknowledging it." This is that acknowledgment. Rewriting ~176 lines of upstream style in-fork would permanently grow our delta and the conflict surface of every future sync — the wrong trade. Budgets were regenerated to the merged tree's actual counts with the repo's own |
c592498
into
litellm_internal_staging
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light.png)
Weekly-cadence upstream pull, following the v1.93.0 (#15) and 2026-07-28 (#24) precedents. We were 497 behind upstream staging / 372 behind upstream main with 78 fork commits ahead; this merges
upstream/main(their release branch, same source as previous syncs).Conflicts: 7, all resolved
test_server_root_path.ymltest-model-map.yamlui package.json+ lockbrace-expansion@5.0.8, consistent with our retained overrideuv.lockruff-strict-budget.json,type-discipline-budget.jsonmake lint-*-budget-updateVerified
plugin_routes.py, duplicate-key checker, grok-imagine + elevenlabs pricing.tests/test_litellm/llms/{kling,xai,fal_ai,elevenlabs,openrouter}), 9.8s.orjsondependency — declared correctly in pyproject, so image builds get it).Also in this PR
openrouter/deepseek/deepseek-v4-flash-0731(the fleet brain since NOL-376) added to both price maps byte-identical — neither upstream branch prices the dated slug, and prod runsLITELLM_LOCAL_MODEL_COST_MAP=True, so the packaged backup map is what actually serves. Until now spend for the fleet brain depended entirely on the litellm-configmodel_infopin; this makes it defense-in-depth. Dup-key check passes.Not in this PR
Deploying the new proxy image.
build.sh --env stg+ stglitellm_image_tagbump + apply is the canary path perimages/litellm/README.md; recommended as the follow-up, prod after stg soak.Pre-existing canonical/backup price-map drift (recraft V4 family is backup-only, from #16) noted but not expanded here — runtime uses the backup, so those prices are live.
Base re-merge and CI follow-ups
litellm_internal_stagingmoved four commits ahead mid-review (MiniMax providers #31, blind-catch narrowing #33, Gemini Veo fixes #34/#35). Merged it in; the only conflict wastest_openapi_compliance.py, where base (#31) and upstream (BerriAI#35161) had independently loosened the same Content-discriminator assertion after Google's spec dropped the keyword. Kept upstream's, a strict superset (accepts a discriminator mapping or a per-varianttypeconst/1-item enum, requires the values be distinct, pins TextContent totext).Also fixed three reds:
uv run --frozenbuilds the litellm-rust bridge via maturin, and the locked aws-sdk crates need rustc 1.94.1 vs the image's 1.92.0. Added the repo's existingsetup-rust-toolchainaction totest-model-map.yaml(12 other workflows already use it). Regenerated the schema too; it was stale onoutput_cost_per_audiobefore this merge.Important
budget-ratchetis red on purpose and needs a human ack (it is non-gating and stays out of required checks by design). Five ceilings genuinely had to rise, because both sides ratcheted independently since the branch point and the merged tree contains both sides' code:BLE001+1,DTZ005230→233,I001267→270,TRY00498→100,LIT00227511→27678. The merge adds no net-new violations: every file's LIT002 count in the merged tree equals one of its two parents. Driving these back down would mean editing upstream code this sync is only carrying.Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is enabled.