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
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)
Redoes #48110 on this line. The lock moves mlflow, mlflow-skinny and mlflow-tracing to 3.17.2, pypdf to 6.21.2 and setuptools to 84.1.0 inside their existing ranges. mlflow 3.17.2 and pypdf 6.21.2 are still inside the 3-day exclude-newer window, so they get their own exclude-newer-package cutoffs, matching main. The lock was regenerated with uv 0.11.7
vitest goes to 4.1.12 and the lock moves vite from 8.3.0 to 8.3.4, along with the rolldown, postcss and nanoid releases that vite 8.3.4 requires, matching main. chai and tinyrainbow stay on their current versions because nothing needs them to move
next goes to 16.4.1, zod to 4.6.6, vite to 7.3.7, and vitest and @vitest/ui to 4.1.12. @vitest/coverage-v8 moves to 4.1.12 as well because it pins vitest to its own version as a peer. A top-level zod override keeps every consumer on the root zod, matching main
The lock only moves these packages and their own @next and @vitest entries, which match the entries on main. A plain npm install also pulled rollup, chai, std-env and a few other dev-only packages to newer releases that nothing required, so those stay on their current versions. sharp is already on 0.35.5 and does not move
Move the OpenTelemetry API, SDK and OTLP exporter pins to 1.45.1 and the FastAPI instrumentation to 0.66b1, which the exporter and mount changes in the previous commit rely on. logfire goes to 5.2.0, and Pillow goes to 13.0.0 on Python 3.11 and newer while 3.10 stays on 12.3.0, matching main
The lock also moves GitPython to 3.2.1, graphql-core to 3.2.12, Brotli to 1.2.1 and pypdf to 6.21.1 within their existing ranges. Brotli 1.2.1 is still inside the 3-day exclude-newer window, so it gets its own exclude-newer-package cutoff. The lock was regenerated with uv 0.11.7 so it stays on revision 3
* fix(deps): upgrade 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
---------
Dependency files (pyproject.toml, uv.lock and the dashboard package.json and package-lock.json) were left out of this pick and re-derived on the 1.106 line in the following commits
The ClientUsagePanel integration test does not exist on this line, so its hunk was dropped
The traceresponse hunks in test_otel_v2_mount.py were dropped because those tests do not exist on this line
Co-authored-by: Yuneng Jiang <yuneng@berri.ai>
(cherry picked from commit 8f9894fbd6)
* 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)
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)
The bundled beta map stripped dangerous-tool-use-2026-09-03 for providers
main supports it on, so safeguards requests went upstream without the beta
whenever the proxy used the bundled map. The worker-SIGKILL chaos test needs
OwnedProxy.replacing_worker, which this line's integration harness lacks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
agentcore/search and vertex_ai/semantic-ranker-default-004 are priced in main's map, so these tests follow main: the search test asserts the mapped per-query price and the custom-pricing rerank test uses an unmapped deployment name.
aiohttp 3.14.3 -> 3.14.5 (yarl 1.23.0 -> 1.25.1 with it), mlflow 3.15.0 -> 3.17.0 (mlflow-skinny and mlflow-tracing with it), claude-agent-sdk 0.1.44 -> 0.2.165 with its dev pin widened to main's ==0.2.165. Every moved version matches main's uv.lock.
Co-authored-by: kerry <kerry@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Backport of #47635 to stable/1.106.x
Cherry-picked from 2cba80cd0d (main)
* 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>
Backport of #47655 to stable/1.106.x
Cherry-picked from 6b1f4ed46f (main)
* 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>
Backport of #47648 to stable/1.106.x
Cherry-picked from 27efc387f7 (main)
* 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>
Backport of #47617 to stable/1.106.x
Cherry-picked from 0c6731eb5c (main)
* 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>
Backport of #47652 to stable/1.106.x
Cherry-picked from ffb7133d32 (main)
* 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>
Backport of #47646 to stable/1.106.x
Cherry-picked from 640f2d865b (main)
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Backport of #47647 to stable/1.106.x
Cherry-picked from 70ece3501f (main)
* 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>
Backport of #47639 to stable/1.106.x
Cherry-picked from 2a268951c4 (main)
* 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>
Backport of #47611 to stable/1.106.x
Cherry-picked from f0ae445cc4 (main)
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>
Backport of #47614 to stable/1.106.x
Cherry-picked from 423362bab2 (main)
* 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>
Backport of #47494 to stable/1.106.x
Cherry-picked from e63aec029a (main)
_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>
Backport of #47416 to stable/1.106.x
Cherry-picked from ad8ca533ca (main)
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Backport of #47571 to stable/1.106.x
Cherry-picked from ccd0d4ea49 (main)
* 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>
Backport of #47490 to stable/1.106.x
Cherry-picked from 7a4a255d1d (main)
Backport of #47625 to stable/1.106.x.
Cherry-picked from 6564a490f4 (main).
Adapted to the line without #45797 or #47494. The router budget limiter claims the batch charge with the line's duration_in_seconds TTL (budget_window_seconds and the injected clock come from #45797, which is not backported), and its realtime skip keeps the line's existing _aresponses_websocket check. The write_started flag on a budget reservation omits the apply_search_free_tier branch, since that flag is #47494's. Tests: the search-allowance accounting test is dropped for the same reason, and the cost-callback and router tests get the litellm and SimpleNamespace imports the line's test files lack.
Backport of #47419 to stable/1.106.x.
Cherry-picked from 3124797399 (main).
Adapted to the line without #41523. Registered rates are tracked per cost-map key in litellm.utils (_registered_pricing_fields, reset when litellm.model_cost is replaced, so a request-scoped registration does not outlive its catalog) instead of AliasedCostEntry.registered_fields. AliasedCostEntry and get_model_cost_map.py are untouched. The register_model replay now merges successive registrations as on main. An inference-profile ARN model_id is reduced to its profile id inside _invoked_model_id_for_cost rather than backporting the get_model_info ARN handling from #46128. Only #47419's lines are taken in completion_cost; base_model_pricing_provider (#46318) and configured search cost (#46571) are not. Tests: CONVERSE_ANSWER added to the slow_upstream helper (it came with #47162, which is not backported), the isolated_pricing_registry fixture and custom-pricing helpers come from main's test file, and the ignore_stamped_cost assertion uses the line's response_cost_calculator signature.
Prerequisite for #47419 on stable/1.106.x. Hand-ports only the helpers #47419 calls from main: ModelInfoLookupMiss, lookup_model_info_for_registration, model_info_with_pricing_overrides with _without_overridden_price_variants and its rate-table helpers (from 9e9dccb9d4, #41523), and runtime_model_cost_registrations (from 3124797399, #47419). runtime_model_cost_registrations reads the line's recorded register_model payloads instead of AliasedCostEntry.registered_fields, so #41523 itself is not backported: register_model, alias entries, cache-price inheritance and unpriced deployments behave as they did on the line.
Prerequisite for #43935 on stable/1.106.x, whose test pins these rows. Ports only the supports_none_reasoning_effort flips for the six azure and azure_ai gpt-6.1-sol rows from 9cf09c18fe (#46377) on main. The rest of #46377 (Azure Responses api-version routing, Grok reasoning tokens, register_model provider refresh) is not included.
Backport of #43935 to stable/1.106.x.
Cherry-picked from d7620c77a1 (main).
Adapted to the line: responses_api_bridge_check lives in litellm/main.py here (moved to litellm/responses/bridge_check.py on main by #45772), so the reasoning_active change and _chat_gate_refuses_reasoning_effort_none are ported there, importing AzureAIGPT5Config locally. Cost-map flags are replayed per model key. Test hunks that conflicted are applied onto the line's files.
Prerequisite for the #47190 integration test on stable/1.106.x. Copied unchanged from tests/integration/_support/prisma_clients.py on main, added there by #45939.