Commit graph

56034 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
e4b47a2bff
Merge nate_messages_native_refusal_fallback_log into integration 2026-11-06 14:35:42 +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
narmstrong-berri
bc8937593e
fix(messages): claim the async success log once across native fallback attempts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013FDwtkaNTifWAP4W7JZavE
2026-11-06 08:59:03 +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
95c05781dd
Merge remote-tracking branch 'origin/nate_messages_native_unchecked_response_body' into nate_messages_integration_local
# Conflicts:
#	litellm-rust/crates/python-bridge/src/routes/messages/host.rs
2026-11-06 07:58:19 +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
8df796fa2e
Merge remote-tracking branch 'origin/nate_messages_native_content_null_fields' 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
9d142431af
fix(messages): pass a 200 body that is not a message through like python
Python's messages transform takes any JSON object from a 200 response and only adds stop_sequence, so a provider answering 200 with an error object reaches the client as 200 and the router counts a success. The native decoder required a full message and turned it into a 500 APIConnectionError and a router failure. A JSON object that is not a message now passes through unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013FDwtkaNTifWAP4W7JZavE
2026-11-06 07:45:04 +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
e9d6610000
fix(messages): keep an explicit null cache_control on native content blocks like python
Python forwards message content blocks as sent. The native request type decoded cache_control: null to None and dropped it when re-encoding, so the provider got a different body. An explicit null now survives the round trip while transforms still see no cache control.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013FDwtkaNTifWAP4W7JZavE
2026-11-06 07:26:21 +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
b20a649ca7
Merge remote-tracking branch 'origin/nate_messages_native_cache_hit_none' into nate_messages_integration_local 2026-11-06 06:21:42 +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
53930e6ef9
fix(messages): leave cache_hit unset on native provider results like python
Python only stamps cache_hit when a result came from the cache. The native logging adapter wrote False on every provider result, so unary success payloads, SpendLogs and failure payloads carried False where Python has None.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013FDwtkaNTifWAP4W7JZavE
2026-11-06 06:16:06 +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
yuneng-jiang
0697cfd6e2
feat(ui): add a beta language setting to the account menu (#50309)
* feat(ui): add a beta language setting to the account menu

The account menu gets a Language field, marked Beta, that lists each language by its own name with the English name beside it. The choice is saved per browser in localStorage and applied with a page reload, so memoized and imperative translations are read fresh.

English stays the default. An unset value, English, an unknown or unsupported code, a locale that fails to load, and any string a locale has not translated all show English. The field stays hidden until a second locale is registered in LOCALES, so this change is invisible until the first translation lands.

* fix(ui): keep the help translate link text inside the link

<link> is a void HTML tag, so the Trans parser dropped its children and rendered an empty anchor. The note now uses <githubLink>, and the language list is at least as wide as its trigger.
2026-11-05 17:50:54 -08:00