Commit graph

54733 commits

Author SHA1 Message Date
Mateo Wang
43dcc2d80a
feat(bedrock): route token counts from model metadata (#47441)
* feat(bedrock): route token counts from model metadata

* fix(bedrock): keep counting metadata compatible with older proxies

(cherry picked from commit 7b82b2a3c3)
2026-10-31 15:46:49 -07:00
yuneng-jiang
f0b9a441b1
Merge pull request #49506 from BerriAI/litellm_ci_5f9963
ci: backport the GitHub Actions integration workflow to rc/1.108.0
2026-10-31 15:22:47 -07:00
yuneng-jiang
5bc605baaf
ci: run the extensions integration group with 48 workers (#49134)
(cherry picked from commit 1a2b443a32)
2026-10-31 14:56:29 -07:00
yuneng-jiang
03f7015f5f
ci: run the integration groups on GitHub Actions (#48985)
* test: add a manually dispatched integration trial on larger runners

Runs the providers, database and management integration groups on 16-core GitHub-hosted runners with Postgres and Redis as service containers, to measure wall time and how far each group scales with more workers

run_integration.sh now keeps a preset INTEGRATION_WORKERS, takes the service container names from the environment, and seeds test order from the GitHub run when there is no CircleCI one

* test: run the integration trial on push to this branch

* test: give integration trial workers a local redis-server

* test: run the providers trial on a 64-core runner with 32 workers

The 16-core run reached 53% of providers in 45 minutes with 16 workers, which points at CPU. Postgres gets max_connections=1000 and a 1 GB shm because one server now backs 32 worker proxies, where each CircleCI machine backs 4

* test: run every integration group in the trial on sized runners

* test: add a scan that refuses to upload integration results holding the license

* test: drop the member-name pass the archive byte scan already covers

* test: use a secret whose base64 and base64url encodings differ

* ci: run integration groups on run-ci pull requests and scheduled main runs

* ci: scope the integration license to a protected environment

Backport note: tests/integration/AGENTS.md keeps rc/1.108.0's text, since main's copy of that paragraph also carries later changes rc does not have

(cherry picked from commit 62b8ee78de)
2026-10-31 14:56:29 -07:00
yuneng-jiang
839bc9fda2
Merge pull request #49167 from BerriAI/litellm_backport_rc_1_108_0_eddb61
fix(mcp)!: backport #48939 to rc/1.108.0, restore upstream-token admission for legacy delegate servers
2026-10-31 14:46:52 -07:00
yuneng-jiang
a78f745b23
Merge pull request #49486 from BerriAI/litellm_chore_935b3f
test: backport three test fixes from main to rc/1.108.0
2026-10-31 13:34:25 -07:00
ryan-crabbe-berri
cd84c7e08c
test(budgets): age the monthly window past any calendar month so the reset test passes on the 31st (#49372)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit 5029d027a1)
2026-10-31 13:00:28 -07:00
yucheng-berri
369d3244fb
test(integration): size restart-mid-burst timeouts from the proxy boot budget (#49376)
Backport note: rc/1.108.0 also needs graceful_stop_seconds imported in test_logging_only_scope_chaos.py, which main already imported

(cherry picked from commit c8c0248ac7)
2026-10-31 13:00:22 -07:00
yucheng-berri
634594b184
test(integration): wait for the stalled-tenant root span and accept a bare POST name (#49406)
(cherry picked from commit 8d202faec7)
2026-10-31 12:41:02 -07:00
yuneng-jiang
4d518568ab
Merge pull request #49172 from BerriAI/litellm_chore_89b3c1
refactor(helm)!: connect both charts to a separately deployed Lens on rc/1.108.0
2026-10-29 20:00:20 -07:00
Yuneng Jiang
a979952bb6
refactor(helm)!: connect both charts to a separately deployed Lens
Neither chart bundles Lens anymore. The Lens subchart, its lock entry,
the vendored chart archive, the templates/lens resources and the
bundled-Lens install smoke are gone. A connection-only lens block wires
the gateway and backend to a Lens deployed from its own chart, and an
enabled lensWorker value fails the render instead of being ignored.

Supersedes #47869, which made the same change for helm/litellm only.

(cherry picked from commit 25b4a24fdd)
2026-10-29 19:28:56 -07:00
Yuneng Jiang
ca461683b6
chore(deps): bump ddtrace to 4.15.6 2026-10-29 18:57:53 -07:00
shrey
18f0d8e0ce
fix(mcp)!: restore upstream-token admission for legacy delegate servers (#48939)
(cherry picked from commit fd8b89fbec)
2026-10-29 18:50:23 -07:00
yuneng-jiang
7a3c6229e1
Merge pull request #48691 from BerriAI/litellm_backport_rc_1_108_0_parity
Some checks failed
LiteLLM Rust / rust-lint (push) Has been cancelled
LiteLLM Rust / rust-test (push) Has been cancelled
LiteLLM Rust / rust-wheel (push) Has been cancelled
fix: bring rc/1.108.0 to parity with the v1.106.x patch fixes
2026-10-28 11:59:35 -07:00
Yuneng Jiang
b359154e4f
bump: litellm-enterprise 0.1.78 -> 0.1.79, litellm 1.107.0 -> 1.108.0 2026-10-27 19:57:39 -07:00
Yuneng Jiang
82925fc3c0
test: accept the mirrored cost map's extraction mode, new row fields and openinfer rows
The mirrored map carries extraction mode rows, explicit_cache_read_input_token_cost and supports_bedrock_native_structured_output, and openinfer rows for a provider this line has no model set for. stable/1.106.x widened the same checks in ebf92c9a45 and f44d4a70c0
2026-10-27 19:57:39 -07:00
Yuneng Jiang
99671ddcf8
chore(model_prices): mirror the cost map from main
Copies model_prices_and_context_window.json and litellm/model_prices_and_context_window_backup.json byte for byte from main at 6083cf9776, the same source stable/1.106.x mirrored in 9225d67f84, so this line carries the exact map v1.106.5 ships
2026-10-27 19:57:39 -07:00
Yuneng Jiang
8521ea164c
build(deps): re-derive uv.lock at main's versions for the 1.106.x parity set
Regenerated with `uv lock --upgrade-package <dep>==<main version>` (uv 0.12.24, the
oldest uv that keeps this lock's revision 5 format) for every package this line had
below v1.106.5: aiohttp, boto3, botocore, brotli, gitpython, graphql-core, grpcio,
logfire, mlflow, mlflow-skinny, mlflow-tracing, the OpenTelemetry 1.45.1 / 0.66b1 set,
pillow (12.3.0 on 3.10, 13.0.0 on 3.11+), pypdf, s3transfer, setuptools and yarl.
Every moved package matches main's lock. uv 0.11.7 and 0.10.9 both pass `uv lock --check`
2026-10-27 19:57:39 -07:00
yuneng-jiang
4e0be6950c
build(deps): bump pillow and dashboard vite, defer certifi to clear osv-scan (#47678)
Pillow 13.0.0 requires Python >= 3.11, so the ci group pin is split by
Python version and the 3.10 resolution stays on 12.3.0 with a 7-day
osv-scanner override. Dashboard vite moves from 7.3.5 to 7.3.7. The
certifi fix (2026.10.19) is still inside the 3-day uv exclude-newer
window, so its advisory is ignored until 2026-10-23

(cherry picked from commit 7c39dbfab8)
2026-10-27 19:57:39 -07:00
yucheng-berri
375df19d63
fix(security)!: build proxy-only failure logs from an allowlist and drop caller guardrail info (#48599)
* fix(proxy): build proxy-only failure logs from an allowlist and ignore request-time GCS credentials

* fix(proxy): drop caller metadata from proxy-only failure logs

metadata and litellm_metadata leave the proxy-only failure-log allowlist, so a rejected request can no longer point its failure log at its own Langsmith or Langfuse host through nested metadata.

* fix(proxy): keep allowlisted metadata in proxy-only failure logs

* test(proxy): isolate proxy-only failure log metadata tests

* fix(logging): ignore non-list request tags when building the logging payload

A guardrail-rejected request with metadata tags set to a non-list value crashed
the standard logging payload, so its spend row lost model attribution.

* fix(proxy): keep router attribution and drop unauthenticated tags in proxy-only failure logs

A request rejected before routing now logs the configured deployment and model group even when its metadata or litellm_metadata carries its own values. Requests rejected at auth no longer write caller tags into failure logs and tag spend.

* fix(proxy): always strip client guardrail info and mirror failure attribution into litellm_metadata

allow_client_pricing_override no longer keeps a caller-supplied standard_logging_guardrail_information on the chat or pass-through paths, since its guardrail_cost is billed. Proxy-only failure logs now also carry key and team attribution in litellm_metadata.

* refactor(proxy): keep the proxy-only failure-log fixes inside the type gates

Types the picked helpers so basedpyright and the type-discipline gate stay at main's counts. No runtime change.

* fix(proxy): keep the WS frame guardrail-info strip and string interaction tags as sent

The guardrail-info key left the pricing strip list, so the Responses WS frame guard now drops it by name. get_request_tags no longer raises on string tags, so background interaction polling checks for them before keeping them as sent.

---------

Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com>
(cherry picked from commit 788868a52f)
2026-10-27 19:57:39 -07:00
yuneng-jiang
89a2d67947
build(deps): bump webpki-roots and webpki-root-certs to 1.0.11 (#48301)
1.0.11 drops emSign Root CA - C1 and emSign ECC Root CA - C3 from the built-in roots

(cherry picked from commit e0982d6248)
2026-10-27 19:57:39 -07:00
yuneng-jiang
e34f7e8c4a
build(docker): refresh base images and ship only runtime files in component images (#48279)
* build(docker): move to newer wolfi-base and nginx base images

Bump the pinned wolfi-base digest in every Wolfi Dockerfile to 360896ef, which
ships brotli 1.2.1-r1 and ca-certificates-bundle 20260909-r3. The previous
digest already carried libbrotli 1.2.0-r6 as an OpenSSL dependency, and
`apk add --no-cache` never upgrades a package the base already has

Move the UI image to nginx 1.31.8-alpine3.24, whose CA bundle is the 20261020
Mozilla set, and upgrade brotli-libs in its runtime stage since no nginx
digest ships 1.2.1 yet

* build(docker): copy only runtime files into the gateway, backend and migrations images

The component runtime stages copied the builder's whole /app, which is the
entire repository plus build output: six lockfiles, helm, terraform, docs,
.env.example and the Rust build tree. Measured at runtime with an audit hook
on a booted container, the gateway reads only gateway/, litellm/ and
enterprise/ from /app, the backend only backend/, litellm/ and enterprise/,
and the migrations job only litellm/ and run.py. The pyproject.toml read is
prisma-python's optional [tool.prisma] lookup, which ours does not define

Copy just those, plus .venv, the entrypoint script and schema.prisma for the
gateway and backend. PYTHONPATH=/app and the in-Dockerfile asserts are
unchanged

(cherry picked from commit dddbaa803d)
2026-10-27 19:57:39 -07:00
yuneng-jiang
016ad90481
fix(docker): update bundled LiteAdmin CA roots and aiohttp (#48139)
Move the liteadmin-builder pin from litellm-admin-agent ef501e9 to
5661c80, which ships certifi 2026.10.19 and aiohttp 3.14.5 in the
/opt/liteadmin venv. That certifi drops emSign ECC Root CA - G3, whose
intermediates were revoked; the earlier bundled-CA updates did not
reach this venv because it installs from the agent's own lock file.

The only other change in ef501e9..5661c80 is the AgentChat bump from
litellm-admin-agent#24 (Slack follow-up routing with models that reject
structured output).

(cherry picked from commit 755fdc570d)
2026-10-27 19:57:39 -07:00
ryan-crabbe-berri
c4fd4051fe
build(deps): bump mlflow, pypdf and setuptools to clear osv-scan (#48110)
(cherry picked from commit 22cfee1534)
2026-10-27 19:57:39 -07:00
yuneng-jiang
e6b82ea754
Merge pull request #48103 from BerriAI/litellm_rotate_cosign_key
chore(signing): rotate the cosign image-signing key

(cherry picked from commit ada3614eb4)
2026-10-27 19:57:39 -07:00
Ishaan
319030c73b
fix(ci): unblock dependency security checks (#48055)
* fix(deps): upgrade vulnerable Python dependencies

* fix(deps): lock patched Python dependency versions

* fix(otel): preserve JSON export with the updated SDK

* test(otel): cover JSON export with the updated SDK

* test(otel): update SDK log records and worker discovery

* fix(ui): align Lens peer dependency with patched Next.js

* fix(otel): hand the AgentOps exporter a session it owns for the JWT header

OpenTelemetry 1.45 moved the OTLP HTTP exporter's requests.Session behind a
transport, so writing the minted JWT to the exporter's private _session raised,
was swallowed, and every AgentOps batch went out unauthenticated. The exporter
now creates the session, passes it through the public session= argument and
sets the Authorization header on it

The tests now drive a real export, serving the token endpoint with respx and
capturing the OTLP POST with requests_mock, instead of reading SDK internals

* fix(otel): skip FastAPI instrumentation once the app has started

opentelemetry-instrumentation-fastapi 0.66b1 wraps build_middleware_stack instead
of calling add_middleware, so instrumenting an app whose middleware stack is
already built no longer raises. The call silently did nothing while we still
registered the global response propagator. Check the built stack up front and
skip both, which is what the existing test expects

* test(otel): assert exported requests and span flags instead of SDK internals

OpenTelemetry 1.45 dropped the exporter's private _headers and sets the W3C
random-trace-id flag on new traces, so traceresponse ends in -03. The Langtrace
and Langfuse tests now export through requests_mock and check the URL and headers
the collector receives, and the traceresponse tests expect the server span's own
trace flags

* fix(deps): bump dashboard zod to 4.6.6 and make the vendored Lens use it

zod 4.6.5 is flagged by the dependency scan and blocks osv-scan on every PR. A
root bump alone leaves the vendored Lens tarball, which pins zod 4.6.5 exactly,
on its own nested copy, so a top-level zod override points every consumer at the
root version and the lock carries a single zod 4.6.6

* test(ui): stub the tag summary fetch the client panel retry refreshes

Retrying the model breakdown refetches /tag/summary, which this integration test
left on the real network. When that request failed before the assertion, the
panel switched to its summary error and unmounted the model row, so the test
passed or failed by timing

* fix(deps): drop the duplicated Lens override from the dashboard package.json

* style(ui): format the client panel fetch stub

---------

Co-authored-by: Yuneng Jiang <yuneng@berri.ai>
(cherry picked from commit 8f9894fbd6)
2026-10-27 19:57:39 -07:00
shrey-berri
a1fd094a3b
fix(security): update bundled CA roots and preserve Prisma image compatibility (#47969)
* fix(security): bump grpcio and boto3 so their bundled CA files drop the compromised eMudhra roots

grpc ignores SSL_CERT_FILE and verifies every channel against its own bundled roots.pem. In 1.78.0 that file still trusts emSign ECC Root CA - G3 and AAA Certificate Services, so Vertex AI, Google KMS, Chirp STT and OTLP gRPC exporters (Arize) accept all 14 advisory chains. 1.84.1 is the first release whose roots.pem drops both roots.

botocore uses certifi when it is installed and falls back to its bundled cacert.pem otherwise. Through 1.43.116 that file still trusts AAA Certificate Services. Requiring boto3 1.43.117 pulls in botocore 1.43.117, the first release whose cacert.pem rejects all 14 advisory chains, so the fallback stays safe if certifi is ever absent

* fix(docker): provide OpenSSL 3 when generating Prisma engines

(cherry picked from commit 52166b51a1)
2026-10-27 19:57:39 -07:00
ryan-crabbe-berri
8cbc115731
fix(security): stop trusting the compromised eMudhra root CA (#47670)
Update certifi, Rust trust roots, and the Docker CA bundle to remove emSign ECC Root CA - G3

Require the fixed certifi release in litellm-core and retain libssl3 in Docker runtimes for Prisma compatibility

Co-authored-by: shin-berri <shin-laptop@berri.ai>
(cherry picked from commit f2118fc767)
2026-10-27 19:57:39 -07:00
Kerry Lu
6c971b7412
fix(proxy): attribute retry attempt spend rows to their deployment and keep them out of daily request counts (#47658)
* fix(proxy): attribute retry attempt spend rows to their own deployment and keep them out of daily request counts

Each <request_id>-attempt-<n> row now carries the model, provider, api_base and model group of the deployment that billed it (looked up by model_info.id through the proxy router, injected as deployment_lookup) instead of copying the final row's, and is stamped internal_call_origin=billed_retry_attempt so the daily spend tables keep its spend and tokens while counting zero api_requests and failed_requests for it

* fix(proxy): declare DeploymentLookup as a TypeAlias and leave the test file's untouched lines as they were

* fix(proxy): mark attempt rows with billed_retry_attempt instead of internal_call_origin so model usage keeps their spend

Bugbot: an internal_call_origin stamp made build_model_usage_transaction drop the attempt rows from LiteLLM_DailyModelUsage. The rows now carry their own SpendLogsMetadata flag, which only the daily request counters read

* fix(proxy): read the billed_retry_attempt flag through a typed helper so the basedpyright gate holds

* fix(proxy): keep the typed litellm_params local in _deployment_provider so the basedpyright gate holds

* fix(proxy): annotate the validated litellm_params as LiteLLM_Params in _deployment_provider

* fix(proxy): keep billed retry attempts out of daily request errors and strip the flag from caller metadata

Bugbot: _record_request_error counted every attempt row as a caller failure in LiteLLM_DailyRequestErrors. Veria: a caller could send metadata.billed_retry_attempt to zero its own request counts, so the key joins the untrusted metadata fields the proxy strips on the way in

* fix(proxy): stamp billed_retry_attempt explicitly in the spend log metadata so the basedpyright gate holds

---------

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit 5dce13d2c2)
2026-10-27 19:57:39 -07:00
Kerry Lu
e1dc2eb201
fix(logging): spilled over PTU requests without base_model log the served model's rates (#47655)
* fix(logging): report pay-as-you-go rates for spilled over PTU requests without base_model

* fix(logging): keep the provider response model so spilled over PTU payloads price the served model

* fix(logging): keep a provider_response_model the response already carries

* fix(logging): read the carried provider_response_model through a typed adapter

---------

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit 6b1f4ed46f)
2026-10-27 19:57:39 -07:00
Kerry Lu
de53be5bc6
fix(proxy): price earlier timed-out retry attempts at their own deployment's model rate (#47648)
* fix(proxy): bill every earlier timed-out retry attempt at its own deployment's model rate

* fix(router): read the retry record's base_model through the typed metadata helper

* fix(router): keep the four-record retry breadcrumb cap

* fix(router): carry a deployment's litellm_params base_model on its retry record

* chore(router): place the cast-ok reason on the cast line and list the base_model helper as covered through log_retry

---------

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit 27efc387f7)
2026-10-27 19:57:38 -07:00
Kerry Lu
99fe893640
fix(router): price cost-based routing through model_info.base_model (#47617)
* fix(router): price cost-based routing through model_info.base_model

* fix(router): keep cost-based routing pricing helpers fully typed

* fix(router): drop typing.cast from cost-based routing pricing helpers

* fix(router): read the cost map through a typed accessor in cost-based routing

* fix(router): avoid a Final rebind inside the cost-based routing loop

* refactor(router): share deployment_pricing_models across spend, listing and cost-based routing

* refactor(router): keep the /v1/models listing key inline, share pricing models for spend and routing

* refactor(router): inline the deployment pricing-model wrapper in cost-based routing

* refactor(router): read deployment pricing models through one shared helper

deployment_pricing_models(deployment) now owns the model_info.base_model / litellm_params.base_model /
litellm_params.model unpacking, used by cost-based routing and the /v1/models listing. pricing_models(base_model, model)
stays for the failure-row spend estimate, which already holds the two names

* refactor(router): share the str-keyed mapping validator with cost-based routing

* ci: re-run after flaky test_aiohttp_transport read timeout in llms-providers

---------

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit 0c6731eb5c)
2026-10-27 19:57:38 -07:00
Kerry Lu
5ebf406610
fix(proxy): price a 499 spend row only for the proxy's own disconnect, and never after the call already completed (#47652)
* fix(proxy): price a 499 spend row only for the proxy's own disconnect, and never after the call already completed

* fix(proxy): gate the zero-cost 499 row on the success log being enqueued, not merely claimed

---------

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit ffb7133d32)
2026-10-27 19:57:38 -07:00
Kerry Lu
453ff99c67
chore(cost-map): add search_free_requests to the model prices schema (#47635)
Co-authored-by: kerry <kerry@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit 2cba80cd0d)
2026-10-27 19:57:38 -07:00
Kerry Lu
642be9bceb
fix(proxy): scope the search free-tier counter to the request's provider (#47646)
* fix(proxy): scope the search free-tier counter to the request's provider

* fix(proxy): read the provider with get so partial spend payloads still get the free tier

* test(proxy): give the grounded spend payload fixture its provider

---------

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit 640f2d865b)
2026-10-27 19:57:38 -07:00
Kerry Lu
432d39c949
fix(proxy): price a billed failure row at the deployment's long-context tier like the success path (#47647)
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit 70ece3501f)
2026-10-27 19:57:38 -07:00
Kerry Lu
dee764834a
fix(proxy): strip caller base_model from spend pricing and reject lone surrogates in multipart metadata (#47639)
* fix(proxy): strip caller base_model from spend pricing and reject lone surrogates in multipart metadata

* fix(proxy): type the parsed multipart metadata so basedpyright does not grow reportArgumentType

---------

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit 2a268951c4)
2026-10-27 19:57:38 -07:00
joshua-berri
bcfbeb86a3
fix(batches): retry confirmed pre-accounting failures (#47625)
* fix(batches): retry confirmed pre-accounting failures

* fix(batches): avoid promising retries for unknown accounting outcomes

* test(batches): exercise real spend writer during retry recovery

* fix(budgets): charge retried batches once per router budget

* test(budgets): cover shared batch charge helpers

---------

Co-authored-by: Joshua Valluru <326636767+joshua-berri@users.noreply.github.com>
(cherry picked from commit 6564a490f4)
2026-10-27 19:57:38 -07:00
Kerry Lu
19a56ba6d1
fix(proxy): bill partial Responses API streams when the client disconnects (#47611)
* fix(proxy): bill partial Responses API streams when the client disconnects

Streamed /v1/responses requests and the default-route OpenAI and Azure /v1/messages requests behind them logged a 499 with zero spend when the client went away mid-stream, while /v1/chat/completions already billed the chunks it had sent. The Responses API iterator now keeps the response.created payload and can hand the disconnect cleanup a response.incomplete event with counted usage and the served service_tier, and the messages-route byte stream and router wrappers delegate to it.

* fix(proxy): satisfy lint gates for partial Responses API disconnect billing

Make the disconnect helper public so the proxy, router and messages adapter can import it without reportPrivateUsage, type the SSE byte stream as an AsyncGenerator so aclose is known, read litellm_call_id off the logging object, and keep the new tests on Final locals with the recorder injected through dynamic_async_success_callbacks instead of litellm.callbacks.

* fix(router): bill the primary stream's tokens after a mid-stream hop and chat-bridge Responses streams on disconnect

The router's fallback wrapper now folds the primary Responses stream's relayed tokens into the fallback's disconnect event the way _combine_responses_fallback_usage does for a natural end of stream, and LiteLLMCompletionStreamingIterator (chat-only providers served through /v1/responses) builds its disconnect event from the chat completion chunks it collected. stamp_responses_usage_cost is now public so the bridge module can price that event.

* Potential fix for pull request finding 'CodeQL / Log Injection'

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

---------

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
(cherry picked from commit f0ae445cc4)
2026-10-27 19:57:38 -07:00
Kerry Lu
5d811fd6c2
fix(proxy): flush the spend-log queue only for Responses turns the bridge reads back (#47614)
Every /v1/responses spend log asked its worker to flush the queue right away so a
chained previous_response_id could find the row. Only the chat-completions bridge
reads that row. Native Responses providers hold the conversation upstream, so their
rows now wait for the batch write like chat rows do

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit 423362bab2)
2026-10-27 19:57:38 -07:00
Kerry Lu
8fab1beda2
feat(proxy): opt-in free-tier allowance for Google Search grounding spend (#47494)
* feat(proxy): opt-in free-tier allowance for Google Search grounding spend

* fix(proxy): declare the search free tier counter's service target

* test(cost_map): allow search_free_requests in the cost map schema

* fix(proxy): skip cache hits and never free more than the billed cost in the search free tier

---------

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit e63aec029a)
2026-10-27 19:57:38 -07:00
Kerry Lu
ffc66f822e
feat(proxy): write one spend row per billed timed-out retry attempt (#47416)
_failure_spend_rows yields the final row plus one re-keyed row per lifted billed_failed_attempts entry (<request_id>-attempt-<position>, the attempt's usage, cost, retry count and deployment id), each written through DBSpendUpdateWriter.update_database so it also deducts from key, team and user spend

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit ad8ca533ca)
2026-10-27 19:57:38 -07:00
Kerry Lu
11a4f8cfbe
fix(proxy): fall back to the deployment model when a billed failure row's base_model is not in the cost map (#47568)
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit 97e5438ffb)
2026-10-27 19:57:38 -07:00
Kerry Lu
7f40419215
fix(proxy): requeue spend logs when a Postgres restart tears down the prisma engine mid-write (#47571)
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit ccd0d4ea49)
2026-10-27 19:57:38 -07:00
Kerry Lu
4d61eba483
feat(proxy): lift every earlier billed timed-out retry attempt onto the failed request (#47490)
* feat(proxy): lift every earlier billed timed-out retry attempt onto the failed request

_billed_earlier_attempts reads the router's previous_models records, keeps the Timeout ones other than the final attempt (matched on deployment_id plus attempted_retries, since the count restarts after a fallback hop and the fallback handler re-logs the exhausting attempt) and prices each at the deployment that served it. post_call_failure_hook lifts the tuple as billed_failed_attempts; nothing writes it yet. previous_models joins the router-reserved metadata fields so a client-planted record never reaches it

* fix(proxy): price earlier timed-out attempts from the prompt estimate only

The final row may lift a mid-stream recovered usage (prompt plus delivered chunks) or a failed_attempts_usage sum; earlier attempts never produced output, so they are priced from _estimated_prompt_usage, and when failed_attempts_usage already bills them into the final row none is lifted again

---------

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit 7a4a255d1d)
2026-10-27 19:57:38 -07:00
joshua-berri
d439837a18
fix(batch): preserve recoverable costs and prevent poll starvation (#47190)
* fix(batch): preserve recoverable costs and rotate polling pages

* test(batch): type retirement failure regression

* fix(batch): alternate new arrivals with retry polling

* test(batch): defer polling row annotation on Python 3.12

* test(batch): reconcile fixtures with atomic metadata claims

* refactor(batch): simplify reconciliation to one bounded scan

* fix(batch): restore arrival priority during retry scans

* fix(batch): preserve recoverable jobs on unrelated resource errors

* fix: revisit recent batches before old retry backlog

---------

Co-authored-by: Joshua Valluru <326636767+joshua-berri@users.noreply.github.com>
(cherry picked from commit 0ede0e10e7)
2026-10-27 19:57:38 -07:00
Kerry Lu
c00f8dace2
fix(decisions): log non-UTF-8 bytes as base64 so the request reaches validation and gets a 400 (#47564)
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit ce63f48ed2)
2026-10-27 19:57:37 -07:00
Kerry Lu
9c991b3d2b
fix(litellm_proxy): forward tool_config cache_control_injection_points to the downstream proxy (#47570)
PR #47394 withheld cache_control_injection_points from the OpenAI SDK extra_body for
every provider on that path, which also covers litellm_proxy. The downstream LiteLLM
proxy applies the point itself, so litellm_proxy keeps forwarding it while OpenAI and the
other OpenAI-compatible providers still never receive it

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit 04e9ed4c52)
2026-10-27 19:57:37 -07:00
Kerry Lu
cb71df770e
fix(logging): report the pay-as-you-go entry billing used on Azure PTU spillover (#47567)
get_standard_logging_object_payload decided custom_pricing from
litellm_params alone, so on an Azure PTU spillover response
model_map_information kept the deployment's zeroed PTU entry while
response_cost already used the standard model rate. Reuse the billing
side LitellmLogging._custom_pricing_for so both read the same decision

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit 4222523261)
2026-10-27 19:57:37 -07:00
joshua-berri
729a29df39
fix(bedrock): resolve profile pricing before applying custom rates (#47419)
* fix(bedrock): price Converse calls using the invoked model profile

* fix(pricing): retain registered rates across metadata updates

* fix(pricing): honor temporary registered prices for Bedrock profiles

* fix(bedrock): record invocation model ID for each completion attempt

* test(bedrock): recalculate fallback cost after metadata updates

* fix(pricing): preserve cache-only registered price overrides

* fix(bedrock): preserve priced overrides without widening shared pricing

* fix(bedrock): retain explicit pricing through token cost lookup

* fix(bedrock): layer cache overrides over invoked profile rates

* fix(bedrock): keep effective prices consistent across billing

* fix(bedrock): share profile pricing and custom rate resolution

* fix(router): remove unused pricing suppression

* fix(cost): preserve rates across mixed token thresholds

* fix(router): share deployment pricing during startup

* fix(bedrock): preserve Router pricing inheritance for profiles

* fix(bedrock): retain configured pricing for unmapped profiles

---------

Co-authored-by: Joshua Valluru <326636767+joshua-berri@users.noreply.github.com>
(cherry picked from commit 3124797399)
2026-10-27 19:57:37 -07:00