Commit graph

21755 commits

Author SHA1 Message Date
narmstrong-berri
3b0689a337
Merge branch 'nate_messages_native_failure_no_wire_headers' into nate_messages_integration_local 2026-11-06 15:13:32 +00:00
narmstrong-berri
1adc411260
fix(messages): state no headers for a native failure without wire headers
A failure the native path raises without an HTTP error response, such as an unreadable 200 body or a header value the client refuses to send, carries no wire headers, and Python logs none for it. The rebuilt response added a content-length from the error text
2026-11-06 15:12:39 +00:00
narmstrong-berri
0bdaee4eef
Merge nate_messages_native_disconnect_error_info into integration 2026-11-06 14:36:20 +00:00
narmstrong-berri
a302596b47
Merge nate_messages_native_header_value_error into integration 2026-11-06 14:36:11 +00:00
narmstrong-berri
505900af58
Merge nate_messages_native_stream_cache_key into integration 2026-11-06 14:36:04 +00:00
narmstrong-berri
2365da61d6
Merge branch 'nate_messages_native_failure_content_length' into nate_messages_integration_local 2026-11-06 14:35:50 +00:00
narmstrong-berri
478c547b24
Merge branch 'nate_messages_native_logged_messages' into nate_messages_integration_local 2026-11-06 14:35:47 +00:00
narmstrong-berri
d1687110fe
fix(messages): bill an abandoned native proxy stream after the disconnect is recorded
The proxy records a client disconnect, with its 499 error information, in the stream generator's cleanup, and the logged payload reads it from metadata. The native teardown billed the stream during cancel propagation, before that cleanup, so the logged row had empty error information
2026-11-06 12:43:48 +00:00
narmstrong-berri
adfdd92ac7
fix(messages): fail a non-string deployment header like python's send
Python's httpx client refuses a non-string header value at send time, after pre_call has logged the resolved call, and the handler maps it to a provider 500. The native handler refused it before the provider request was logged and surfaced an APIConnectionError, so retries, cooldowns and the failure log differed
2026-11-06 11:07:52 +00:00
narmstrong-berri
afdb87d7a2
fix(messages): log the request body as input on native messages calls
Python's messages handler calls pre_call with the request body as a json user message, and a stream's spend-log cache_key is computed over that input. The native adapter logged the string Messages, so a streamed call's cache_key differed from Python's
2026-11-06 09:56:00 +00:00
narmstrong-berri
f254d57f38
fix(messages): drop wire length and encoding headers from native upstream failures
Python raises upstream error statuses as MaskedHTTPStatusError, which rebuilds the httpx response from the decoded body without content-encoding and content-length, so an empty error body logs no content-length. The native failure passed the wire headers through and logged content-length 0
2026-11-06 09:33:42 +00:00
narmstrong-berri
93678af097
fix(messages): log the sent messages and the caller's params on native messages calls
Python updates model_call_details with the transformed request body before pre_call, so the logged messages are what was sent. The native adapter kept the caller's messages and compared the caller's params to the sent ones as JSON values, so an int 0 logged as 0.0
2026-11-06 09:07:09 +00:00
x
0e6ecc785a
Merge remote-tracking branch 'origin/nate_messages_native_timeout_failure_spend' into nate_messages_integration_local
# Conflicts:
#	litellm/rust_bridge/host/routes/messages.py
2026-11-06 07:58:27 +00:00
x
935a6fd0cd
Merge remote-tracking branch 'origin/nate_messages_native_connect_error_class' into nate_messages_integration_local 2026-11-06 07:58:07 +00:00
x
f56b36e5b5
Merge remote-tracking branch 'origin/nate_messages_native_fallback_precall_provider' into nate_messages_integration_local 2026-11-06 07:58:07 +00:00
x
72982452b9
Merge remote-tracking branch 'origin/nate_messages_native_logged_model_params' into nate_messages_integration_local 2026-11-06 07:58:07 +00:00
x
531ea9707f
Merge remote-tracking branch 'origin/nate_messages_native_cache_hidden_params' into nate_messages_integration_local 2026-11-06 07:58:07 +00:00
narmstrong-berri
788c4dae51
fix(messages): bill a native read timeout's prompt on the failure row like python
The proxy bills the estimated prompt of a failed call only when the Timeout was caused by an httpx ReadTimeout. The native timeout carried no transport cause, so its failure SpendLogs row and spend counters showed 0 where Python bills the prompt. The native timeout now chains the same httpx timeout Python's client raises.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013FDwtkaNTifWAP4W7JZavE
2026-11-06 07:57:40 +00:00
narmstrong-berri
26a2eab2d9
fix(messages): raise python's transport error class when a native call never gets a response
Python wraps a connect, DNS, TLS or reset failure in a synthesized 500 AnthropicError, which maps to InternalServerError with the transport's own text. The native path sent these through the generic fallback, so they surfaced as APIConnectionError with the bug-report footer, which also changes cooldown decisions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013FDwtkaNTifWAP4W7JZavE
2026-11-06 07:40:00 +00:00
narmstrong-berri
0b52efe0bf
fix(messages): keep the provider out of a shared logger's litellm_params on native messages calls
Python's messages handler only records custom_llm_provider in model_call_details. The native adapter also wrote it into litellm_params after every provider result, and the proxy reuses one logger across router hops, so a fallback hop's pre_call log showed the provider where Python shows null.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013FDwtkaNTifWAP4W7JZavE
2026-11-06 07:25:27 +00:00
narmstrong-berri
a67684d814
fix(messages): log the caller's messages params on native calls like python
Python logs the requested optional params, taken before the provider transform, as model_parameters. The native handler logged the transformed body, so a reasoning_effort request was logged as thinking and output_config. The request context now carries the requested params.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013FDwtkaNTifWAP4W7JZavE
2026-11-06 07:11:33 +00:00
narmstrong-berri
3176f55592
fix(messages): write the native unary cache entry after the router stamps it like python
Python stores a unary messages response from a background cache write task that runs after the router stamps _hidden_params, so the entry carries model_id and the router headers and a later hit returns x-litellm-cache-key. The native path stored the entry inside the native call, before the router saw the response. The async unary store is now deferred until the route encodes its public response and is handed to Python's own cache write task.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013FDwtkaNTifWAP4W7JZavE
2026-11-06 06:35:39 +00:00
x
e83e1363f9
Merge remote-tracking branch 'origin/nate_messages_native_during_call_mask' into nate_messages_integration_local
# Conflicts:
#	litellm/messages/dispatch.py
2026-11-06 06:21:53 +00:00
x
06077ecb0b
Merge remote-tracking branch 'origin/nate_messages_native_disconnect_billing' into nate_messages_integration_local 2026-11-06 06:21:42 +00:00
x
994f051d61
Merge remote-tracking branch 'origin/nate_messages_native_timeout_header' into nate_messages_integration_local 2026-11-06 06:21:42 +00:00
x
bc84440494
Merge remote-tracking branch 'origin/nate_messages_native_stream_cut_error' into nate_messages_integration_local 2026-11-06 06:21:42 +00:00
narmstrong-berri
0f56397c0c
fix(messages): hold native sync success callbacks until the proxy releases the log
Python runs sync success callbacks inside the deferred logging closure, so a post-call hook that blocks the response drops them. The native adapter ran them right away, so a guardrail block still fired sync loggers. A parked native success now carries its sync callbacks and runs them on release.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013FDwtkaNTifWAP4W7JZavE
2026-11-06 06:17:26 +00:00
narmstrong-berri
74ccfc50b4
fix(messages): let during_call guardrail edits reach the native request
Python's messages handler yields to the event loop before it builds the provider body, so a during_call guardrail started next to the call masks the request first. The native path built its request without yielding, so masked text never reached the provider. The async native dispatch now yields once before calling the native hook.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013FDwtkaNTifWAP4W7JZavE
2026-11-06 06:12:16 +00:00
narmstrong-berri
d8053b7eb4
fix(messages): bill a native stream the client abandoned like python does
When the client disconnects mid-stream, the native adapter now logs success for the chunks it delivered before teardown, so spend, SpendLogs and the key's budget and tpm reservations settle the same way they do on the Python path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013FDwtkaNTifWAP4W7JZavE
2026-11-06 05:45:42 +00:00
narmstrong-berri
52e0bffd16
fix(messages): stamp timeout and num_retries on native messages failures
Python's async client wrapper stamps the effective timeout and num_retries on every failure, which the proxy reads for x-litellm-timeout and the router reads for retries. The native async path skipped that wrapper, so error responses from Rust-served /v1/messages calls had no x-litellm-timeout header
2026-11-06 05:35:50 +00:00
narmstrong-berri
76331043ae
fix(messages): surface a cut native stream as the transport error python raises
A Messages stream whose upstream body ends mid-frame reached proxy callers as a mapped APIConnectionError with status 500, a stray NoneType line and a bug-report notice. Python's transport raises an unmapped httpx error at that point. The native body read now records a body cut (received, expected, reset) and the host raises the same exception the active transport would, logs the chunk-processor line and leaves cache_hit unset
2026-11-06 05:30:38 +00:00
narmstrong-berri
eeebcdcdbb
fix(proxy): release parked native success logs for every call type
The proxy defers non-stream success logging past post-call guardrails, and the native host parks its log on _native_pending_logging until the proxy releases it. The release only ran for OCR, so a unary /v1/messages call served by Rust logged no success event, no SpendLogs row and no key, team, user or end-user spend
2026-11-06 05:24:37 +00:00
narmstrong-berry
1d46ade6da
fix(messages): let proxy /v1/messages requests run on the rust path
The proxy attaches its shared aiohttp session to every request and a default stream_timeout to every stream, and the messages detectors treated both as Python-only features, so no proxy request reached Rust. The native client keeps its own pool and already applies stream_timeout as the stream's timeout, so only an explicit client, request_timeout or httpx.Timeout keeps a messages call on Python
2026-11-06 04:26:09 +00:00
ryan-crabbe-berri
6fa0477d84
test(e2e): add a Codex row that calls a local MCP tool on a first and a resumed turn (#49817)
* test(e2e): add a Codex row that calls a local MCP tool on a first and a resumed turn

* test(e2e): assert the codex mcp row got each value back from the mcp tool call itself

* test(e2e): check the codex mcp row exits cleanly on both turns

* test(e2e): drop the unused content type from the codex mcp result model
2026-11-06 03:59:03 +00:00
jesus-berri
4f06ca217f
feat(team): let default_team_params attach access_group_ids to every new team (#49908)
* feat(team): let default_team_params attach access_group_ids to every new team

* fix(types): keep default access_group_ids as Sequence for the type discipline gate

* fix(settings): chunk the default access group existence lookup

* test(team): prove default access groups reach the saved team row and type the settings fixtures

* fix(team): check default access groups on the writer so a fresh group is not rejected behind a read replica
2026-11-05 19:58:51 -08:00
jesus-berri
18b02380e5
feat(spend-logs): opt-in latest_turn mode that stores only the current turn of stateless requests (#49544)
* feat(spend-logs): opt-in latest_turn mode that stores only the current turn of stateless requests

* fix(spend-logs): keep bridged Responses rows and classifier audit in latest_turn mode, reject unknown values at boot

* fix(spend-logs): drop the recursive call in the latest_turn trim and type the stateless test cases

* test(spend-logs): format the stateless latest_turn cases

* test(spend-logs): wrap the classifier audit fixture

* fix(spend-logs): type the latest_turn trim inputs

* fix(spend-logs): leave the raw request body unvalidated before the latest_turn trim

* fix(spend-logs): trim classifier rows and ignore continuation keys off /v1/responses in latest_turn mode

* fix(spend-logs): take the classifier's originating request from the logging payload and redact a copy of vector store results

* fix(spend-logs): redact the body selected for storage, after the latest_turn trim
2026-11-05 19:41:15 -08:00
ryan-crabbe-berri
9a473fbbb0
feat(proxy): give Codex accurate model entries for every model in /v1/models (#49825)
* feat(proxy): give Codex accurate model entries for every model in /v1/models

* fix(router): read a deployment's upstream model without a not-required key access

* fix(proxy): keep Codex tiers for unpriced deployments and match stock entries by declared provider

A deployment with no token price no longer votes a Codex service tier off,
an undescribed model keeps Codex's default reasoning summary parameter,
a Bedrock deployment naming its provider in custom_llm_provider gets Codex's
stock entry, and Bedrock provider namespaces follow the AWS model id format.

* fix(proxy): import cost tracking and provider helpers lazily in the Codex catalog

lite codex imports the catalog before the SDK is initialized, so importing
cost tracking, the Bedrock helpers or provider resolution at module level hit
a circular import and broke every lite command.

* fix(proxy): drop Codex's fast speed tier wherever its priority tier is dropped

Codex shows /fast for a leftover fast speed tier even when service_tiers
no longer offers priority, so an alias, an empty configured tier list or
a configured list without priority showed a /fast toggle that sends nothing.
One helper now sets service tiers, speed tiers and the default together.

* fix(proxy): give an older Codex a translated entry for models past its version

Codex's own entries name the oldest release that can read them in minimal_client_version. A release older than that can fail to decode the entry, such as a reasoning effort it has no name for, which fails the whole catalog, so it now gets the translated entry, whose levels are trimmed to that release
2026-11-05 19:31:32 -08:00
yujonglee
a1b87bcca8
feat(redis): extend the native Redis foundation for the store families (#50169)
Reworks the redis-client, connect, resolve and testing crates, adds python-compat json loads and
TTL seconds, replaces the redis-store memory tier with a DualCache plus a shared failure log, and
gives the Python side the Redis timeout log throttle and a request OTEL parent span for service events

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 12:30:07 +09:00
ryan-crabbe-berri
48ff826cbc
feat(proxy)!: only let clients pick S3 buckets the admin allowed (#47496)
* feat(proxy): let admins allow specific S3 buckets and endpoints in request bodies, block bucket settings otherwise

Client requests can no longer pick s3_bucket_name, s3_output_bucket_name or allow_legacy_cloud_file_ids unless the
value is on general_settings.allowed_client_side_s3_buckets (buckets) or the admin opted in the usual way.
s3_endpoint_url, already blocked, can now be allowed per value through general_settings.allowed_client_side_s3_endpoint_urls

* refactor(proxy): drive the client-side S3 allowlist from one typed field-to-setting map

* fix(proxy): treat a null client-side S3 allowlist in config as empty instead of failing the request
2026-11-06 02:50:15 +00:00
qtim0
5085022580
fix(audio-transcription): keep transcripts out of transcription error messages (#50137)
* fix(gemini): omit raw response body from audio transcription error messages

* fix(gemini): raise incomplete transcription interactions as non-retryable 400 and drop response bodies from Vertex transcription errors

* fix(audio_transcription): keep response bodies out of transcription errors

Keep the upstream status on a Gemini interaction that did not complete, so
the router still retries it as it does on main. Gemini stops the same long
clip on some tries and not on others, so a retry can recover it.

Stop quoting the reply in the Deepgram, ElevenLabs, Watsonx, Mistral,
OVHcloud and Scaleway parse errors, and hide pydantic input values on the
Gemini and Vertex response models.

* fix(audio-transcription): keep reply bodies out of watsonx, whisper, xai and validation errors

Watsonx and whisper no longer print the parsed reply after Got: when it has no text field. TranscriptionResponse and the xAI response model hide input in validation errors, so a malformed field cannot quote transcript fragments. Deepgram and ElevenLabs keep the original error text, which is now safe.

* fix(audio-transcription): keep transcripts out of the shared converter's parse errors

* test(audio-transcription): compare wrapped lookup errors instead of pinning upstream wording

---------

Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com>
2026-11-05 18:07:15 -08:00
Kerry Lu
8ac9da84f7
fix(router): drop supports_web_search false deployments for Anthropic web_search_* and Gemini googleSearch tools (#50275)
* fix(router): drop supports_web_search false deployments for Anthropic web_search_* and Gemini googleSearch tools

* test(integration): build the web search filter proxy config without mutating the shared config

---------

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-11-06 01:58:17 +00:00
yucheng-berri
9f489430a6
fix(proxy): probe scrypt instead of MD5 in the fips_mode OpenSSL check (#50305)
* fix(proxy): probe scrypt instead of MD5 in the fips_mode OpenSSL check

* test(proxy): fake a working scrypt so the fips_mode check tests pass on FIPS hosts
2026-11-05 17:43:32 -08:00
devin-ai-integration[bot]
d96da7267b
test(copilot): route direct-token fixtures through authenticated peers (#50307)
Co-authored-by: mateo <277851410+mateo-berri@users.noreply.github.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-11-05 17:42:46 -08:00
Mateo Wang
d947ec1f7d
refactor(prompt_templates): move JSON schema helpers out of common_utils into json_schema_utils (#50241)
* refactor(schema): extract JSON schema helpers from prompt utilities

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* Extract cohesive prompt utility modules

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* Preserve legacy prompt utility aliases

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>
2026-11-05 17:25:53 -08:00
Mateo Wang
14d50ed40d
feat(bedrock): default to native structured output on Opus 5 and Opus 4.8 (#50222)
* feat(bedrock): enable native structured output for Opus 5 models

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(bedrock): keep govcloud and bare model rows off native output

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(bedrock): retry rejected native schemas with the JSON tool on default-native models

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(bedrock): keep the rejection retry on the unforceable-tool native path

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(bedrock): retry rejected schemas on the Messages path for default-native models

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(bedrock): keep JSON-tool streaming coverage on unchanged route

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* style(bedrock): format Messages native output retry

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(bedrock): allow profile-only native output metadata

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(bedrock): only disable default-native output on schema-rejection retries

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(bedrock): type fixture parameters in native output retry tests

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(bedrock): retry with the JSON tool when Bedrock rejects a schema's grammar size

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(bedrock): drop strict tools after a native-output retry hits the grammar limit

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* style(bedrock): format native output fallback

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>
2026-11-05 17:22:17 -08:00
mrinal-berri
fb2a1450dd
fix(users)!: validate custom IDs and reject concurrent duplicate creation (#49748)
* fix(users): validate custom IDs and reject concurrent duplicate creation

* fix(users): return precise conflicts without retrying them

* fix(users): preserve retries for existing-user upserts

* fix(scim): preserve opaque IDs during user provisioning

* fix(sso): preserve identity provider user IDs
2026-11-05 17:07:19 -08:00
tin-berri
a7f9f892be
feat(skills): add sortable Skills Hub catalog and publication audit (#50195)
* feat(skills): add sortable Skills Hub catalog and publication audit

* refactor(skills): remove redundant publisher table column

* style(skills): apply dashboard formatting

* fix(skills): preserve approval audit and complete hub sorting
2026-11-06 00:57:33 +00:00
yujonglee
79710a6ff1
feat(packaging): build litellm-proxy gateway wheels (#49605)
* feat(packaging): ship litellm-proxy wheels with the proxy extra

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(packaging): keep litellm-proxy out of the proxy extra until PyPI has it

The current release pipeline publishes litellm with whatever pyproject.toml lists, so pinning an unpublished package would break pip install litellm[proxy]. Images and CI still install the locally built gateway wheel

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 16:37:12 -08:00
Kerry Lu
d295f76c4a
fix(types): define the responses compact call types for during_call guardrails and deployment hooks (#50274)
* fix(types): define the responses compact call types so during_call guardrails and deployment hooks see them

* test: regenerate dashboard api types and skip compact in the azure sdk client sweep

---------

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-11-05 16:09:49 -08:00
Nate Armstrong
58896e2009
test(router): expect a primary stream's stall to cool its deployment (#50261)
The primary stream's mid-stream stall reaches failure_exits as a mapped litellm.Timeout (408), which cools the deployment on the Rust core. Keep that behavior and update the integration test that expected the Python core's exemption. Fallback hops stay exempt through is_stream_stall.
2026-11-06 00:06:59 +00:00