Commit graph

80 commits

Author SHA1 Message Date
Yujong Lee
eb502824f0 fix stuff 2026-09-19 09:32:46 -07:00
Yujong Lee
c404bed9f0 feat(rust): add Amazon Textract to litellm.ocr and sign provider requests after host hooks
Add an aws_textract OCR provider on the Rust route, with no Python path. The
detect-document-text model returns plain lines and analyze-document renders
layout and tables as markdown. Both use Textract's synchronous API, so a
multi-page PDF or TIFF is rejected with an error that names the single-page
limit. A call with no region fails instead of falling back to Bedrock's default

SigV4 covers the request body, and host hooks can rewrite that body before it
is sent. litellm-http now has OutboundRequest, which serializes the body once,
shows those bytes to a RequestSigner and is the only thing a route can send.
Chat, audio transcription and OCR build it after their hooks ran, so a callback
that redacts the body still produces a valid Bedrock or Textract signature

ChatCompletionsAuth and AudioTranscriptionAuth are replaced by
litellm_auth::RequestAuth, and one helper in core turns it into a signed or
unsigned request. Audio transcription now signs only the AWS header set and
rejects a forwarded header that SigV4 computes, the same as chat

The OCR catalog routes aws_textract as Rust required, and the dispatch context
reads the provider from the model prefix so a provider scoped rule can match
2026-09-19 09:11:52 -07:00
Yujong Lee
0a00021722 fix(rust): resolve Mistral OCR credentials in Python's env order
Python resolves the Mistral key as api_key, MISTRAL_AZURE_API_KEY, then
MISTRAL_API_KEY, and the base as api_base, MISTRAL_AZURE_API_BASE, then
the public endpoint, never reading MISTRAL_API_BASE. Native OCR read
MISTRAL_API_KEY and MISTRAL_API_BASE instead, so with the Azure pair set
it sent the call to a different endpoint with a different key. Empty env
values now fall through like Python's `or` chain.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 07:33:02 -07:00
Yujong Lee
1ee4b62e9c fix(rust): honor vertex_project, vertex_location and enable_azure_ad_token_refresh globals
Python resolves the Vertex project and location as call params, then the
litellm.vertex_project / litellm.vertex_location globals, then env, and
Azure AD token refresh from litellm.enable_azure_ad_token_refresh alone.
Native OCR skipped the globals, so a config.yaml litellm_settings value
silently fell through to the credential's project and us-central1, and a
managed identity setup without an API key failed. The bridge now reads
them through a provider_defaults settings group into OcrSettings, and
VertexConfig / AzureAuthInputs slot them in at Python's precedence.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 21:01:37 -07:00
Yujong Lee
0d76359dc9 fix(rust): resolve OCR provider env fallbacks through the secret manager
Python reads every provider credential fallback (MISTRAL_API_KEY,
AZURE_AI_API_KEY, AZURE_DOCUMENT_INTELLIGENCE_ENDPOINT, Azure AD and
Vertex env, ...) through get_secret_str, which consults the configured
key_management_system before os.environ. Native OCR read std::env
directly, so a key held only in the vault went missing and a stale env
copy silently won. OcrClient now carries an injected secret Lookup that
the connection exposes to providers and auth crates; the bridge backs it
with settings.secret -> get_secret_str, pure Rust keeps the process env.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 20:57:24 -07:00
Yujong Lee
c0705f31b4 fix(rust): read OCR env-backed constants instead of hardcoding their defaults
Native OCR hardcoded the default of five Python constants that come from
env vars, so an operator setting them saw no effect:
REQUEST_TIMEOUT (Rust used 600s, Python 6000s), MAX_IMAGE_URL_DOWNLOAD_SIZE_MB
(0 disables document downloads), AZURE_OPERATION_POLLING_TIMEOUT,
AZURE_DOCUMENT_INTELLIGENCE_API_VERSION and
AZURE_DOCUMENT_INTELLIGENCE_DEFAULT_DPI. OcrSettings reads them through
Lookup with Python's parsing, the bridge builds it per call and OcrClient
carries it into the connection. A zero per-call timeout now falls back to
REQUEST_TIMEOUT, matching `timeout or request_timeout`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 20:51:55 -07:00
Yujong Lee
d77c144c6c refactor(rust): split custom_httpx into litellm-http and the OCR handler
custom_httpx mirrored a Python module that mixes transport plumbing with
OCR orchestration. The transport half (media fetcher, transport errors,
request and header helpers) now lives in litellm-http next to the pool,
TLS, proxies and settings, and the OCR request handler moves to
base_llm/ocr/handler.rs. Drops the unused deserialize_optional_param and
stale dead_code allows.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 20:46:36 -07:00
Yujong Lee
80dbb2a28a refactor(rust): resolve the http client config through From and TryFrom
HttpClientConfig::resolve becomes From<&HttpSettings> for Resolution and client_builder becomes TryFrom<&HttpClientConfig> for reqwest::ClientBuilder, matching the rustls conversion. The verify decision moves into From<&HttpSettings> for Verify, and the proxy environment rule moves next to its flags as HttpSettings::trusts_proxy_env. The curve and cipher results are read with transpose and a default selection, which removes the tuple destructuring
2026-09-18 19:48:34 -07:00
Yujong Lee
51010ea486 feat(rust): serve every gateway HTTP setting natively instead of declining to Python
litellm-http now builds the rustls config itself, so one route-neutral place covers roots, the client certificate, ALPN, ssl_ecdh_curve and ssl_security_level. A curve picks the single key exchange group. A cipher string restricts the TLS 1.2 suites it names, and entries rustls cannot express, such as @SECLEVEL=1, are logged once and skipped.

user_url_validation and user_url_allowed_hosts are applied by the media fetcher. Document downloads honor the environment proxy whenever provider calls do, keeping the per-hop address check, and stay on the pinned resolver when no proxy applies.

AIOHTTP_SO_KEEPALIVE, AIOHTTP_TCP_KEEPIDLE, AIOHTTP_TCP_KEEPINTVL, AIOHTTP_TCP_KEEPCNT and AIOHTTP_KEEPALIVE_TIMEOUT map onto the client. A client= argument and a live SSLContext are ignored
2026-09-18 19:39:07 -07:00
Yujong Lee
b2d6cd1fcf refactor(rust): read litellm HTTP globals through one Python shim and tighten the http pool
Drop the core ocr() facade so VertexAuth and the http pool stay out of litellm-core's
public API, move the http Error enum to error.rs, and inject the media DNS resolver into
HttpClientPool instead of a per-call builder hook the cache key ignored.

The bridge now reads litellm.* HTTP settings only through litellm/rust_bridge/settings.py,
pinned by python_settings.json, while env overrides stay in Rust. This adds the Python
default User-Agent, parses string ssl_verify globals like get_ssl_verify, drops per-call
ssl_verify that Python OCR never honored, and removes the unused request_timeout.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 17:23:26 -07:00
Yujong Lee
b6b5ef00cc chore: merge main into litellm_rust_http_pool_ocr
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-19 00:10:17 +00:00
Yujong Lee
5a474fd799 refactor(rust): inject VertexAuth into OcrClient so the bridge keeps one token cache
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-18 23:31:27 +00:00
Yujong Lee
abb9618971 feat(rust): add litellm-http client pool and inject it into the OCR route
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-18 23:28:11 +00:00
Yujong Lee
41873e2bc7 fix(rust): box messages response output
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-18 15:45:08 -07:00
Yujong Lee
b7686d78b6 refactor(rust): move RouteMachine out of core into litellm-host next to the Machine trait
core/src/machine was route-neutral runtime code sitting among route surfaces, and the workspace had two modules named machine. It now lives in litellm-host beside the contract it implements, so core only holds routes. The OCR conversion from MachineFault moves to litellm-llms because the orphan rule no longer allows it in core
2026-09-18 15:45:08 -07:00
Yujong Lee
19ffb584eb refactor(rust): rename litellm-callbacks to litellm-host and HostOpError to InvokeError 2026-09-18 15:45:08 -07:00
Yujong Lee
3a5b7c12ef refactor(rust): separate machine events from the Python lifecycle's events 2026-09-18 15:45:08 -07:00
Yujong Lee
1a52bae779 add streaming message 2026-09-18 15:45:08 -07:00
Yujong Lee
b4bfd92a2a refactor(rust): route-neutral callback contract
Every legacy callback call from callbacks-legacy now goes through one typed
Python shim, litellm.rust_bridge.legacy_callbacks, the only Python module
the crate reaches. Before, the crate called Logging methods, litellm.utils
hooks, the logging worker, the executor and several litellm globals
directly, and its tests retyped those signatures by hand, so an outdated
fake could accept a call the real code rejects. python_contract.json lists
each shim function's parameters: a Python test pins it to the real
signatures and a Rust test pins it to the Rust enum.

The lifecycle contract changes to match the Python @client wrapper:
- the driver emits CallEvent::Started before begin, so every host sees one
  start time
- RequestContext carries the route-resolved api_key, so legacy pre_call and
  post_call receive it, and post_call's additional_args match the Python OCR
  path
- Passthrough and its re-aliasing are gone
- async deployment hooks always run, and the "no callbacks" shortcut that
  skipped the logging payload is removed, as in the Python path

The OCR api_key is a SecretValue from the wire request onward, so Debug
output upstream of the callback contract cannot leak it.

host-python's RouteHost now classifies native failures once through
classify, and host ops return HostOpError. The OCR route host keeps main's
public errors by sending both through the existing Python map_failure.
2026-09-18 15:43:08 -07:00
Yujong Lee
5a76346047 refactor(rust): move OCR provider code into litellm-llms and delete core/src/llms
OCR transformations, BaseOcrConfig with its response and connection types,
the OCR error, and the HTTP pieces (custom_httpx: http_handler, transport,
media, llm_http_handler with OcrClient and the request/response handler)
now live in litellm-llms at their Python paths. Provider code no longer
reaches into the route: it gets the caller's hooks through a route-neutral
CallHooks trait that core implements over its host, and core dispatches to
llm_http_handler::ocr with the concrete config, the way Python calls
base_llm_http_handler.ocr(provider_config=...).

Core keeps the route: entrypoint, request types, credential fallback,
provider dispatch, the machine and hook glue. ocr/mod.rs no longer
re-exports anything, provider constants moved next to their only users,
and provider tests that drive the whole route moved to core's route test
files. Twenty-two of those were exact copies of tests already there and
were dropped; every one still runs once.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 22:29:08 -07:00
Yujong Lee
49c50739d7 refactor(rust): rename providers to llms and move non-OCR provider code out of core
litellm-providers becomes litellm-llms, mirroring litellm/llms. The Anthropic
batches, count_tokens, Messages stream iterator and chat stream handler, the
OpenAI Responses websocket config and its base trait (with URL and model
helpers), and the StreamTransformer base iterator now live at their Python
paths in that crate. Anthropic stream decode errors move with the iterator,
and core drops its duplicate OAuth prefix constant and the unused framing
dependency.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 22:04:16 -07:00
Yujong Lee
904c679595 refactor(rust): add types and core-utils crates, unify the provider error
litellm-types mirrors litellm/types (chat, Anthropic Messages and Responses
websocket data) and litellm-core-utils mirrors litellm/litellm_core_utils
(provider resolution, prompt factory, core helpers, call arguments). Route
request types move up to their core route module, the transform contracts
move into base_llm, and the three duplicated provider error enums become one
Error in base_llm/chat/transformation.rs, mirroring BaseLLMException.

The empty-text placeholder goes back to the value Python's factory.py uses;
the provider extraction had changed it to a single space.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 22:01:14 -07:00
Yujong Lee
63d994ade4 refactor(rust): run OCR through a route-neutral callback contract and a legacy Logging adapter
Extracted from #41733 without the router loop, the cache machine layer, streaming, or the
error, timeout and route-pruning work that moved to #41745

litellm-callbacks holds the contract a native call and its host share: Machine, HostOp,
CallEvent, the in-process run loop, and Passthrough, which is built only by comparing the
caller's inputs with the body the route sends, so a route can never mark a key it rewrote.
litellm-host-python (formerly python-interop) owns the CPython driver and the Execution
handle, and litellm-callbacks-legacy is the @client wrapper as the native call sees it:
function_setup, the deployment hooks, pre_call and post_call, the success and failure fan-out
and the deferred proxy release. OCR is the one route on it, and the old core and bridge
lifecycles are gone

The passthrough rule is the structural fix for the bug #41719 patched in core and #41716
reworks: an inlined remote document no longer counts as the caller's value, so the legacy
adapter never hands the caller's URL back into the body. core/tests/ocr/passthrough.rs pins
it for every route and document source, including that unchanged values stay passthrough,
and callbacks-legacy/tests/payload.rs pins the adapter side with a real pre_call callback

Python OCR integration tests that only exercised core behavior now live as Rust tests, so
tests/test_litellm_rust keeps the cases that need the full Python stack
2026-09-17 21:13:16 -07:00
Yuneng Jiang
726dbf0d0d
fix(ocr): keep a downloaded document inlined when callbacks intercept the request
Providers that cannot fetch a public document URL themselves (Azure AI
mistral document AI, Azure cohere parse, Vertex AI) download it and
inline it as a data URI. When a pre-call callback or debug logging
intercepts the request, the Python host hands the caller's original
document back into the body, so the provider request carried the URL
again and Azure's inline-only check rejected it with "invalid OCR
document data URI". The core now keeps the prepared document when a
hook returns the untouched caller document, while a hook that edits or
replaces the document still wins
2026-09-17 17:48:52 -07:00
Yujong Lee
6ce78b85a5 refactor(rust): remove core provider reexports
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-17 22:55:15 +00:00
Yujong Lee
558022c3dd refactor(rust): extract provider translations
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-17 22:46:02 +00:00
Yujong Lee
766f45e0eb merge: resolve conflicts with main for anthropic layout rename
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-17 18:09:27 +00:00
Yujong Lee
f1ea94fee7 make test pass 2026-09-17 08:55:59 -07:00
Yujong Lee
370cdaabf9 encode failing tests 2026-09-17 08:04:52 -07:00
Yujong Lee
b063ffe883 providers folder is gone 2026-09-17 07:52:14 -07:00
Yujong Lee
27ccf7326b mistral alignment 2026-09-17 07:33:06 -07:00
Yujong Lee
ab1f966a17 test coverage 2026-09-17 07:10:49 -07:00
Yujong Lee
0e5f41bc93 refactor(rust): drop unused OpaqueParams body-composition helpers 2026-09-17 06:54:18 -07:00
Yujong Lee
3ad91fc27e fix(ocr): run hooks on completed Azure poll 2026-09-17 06:53:19 -07:00
Yujong Lee
0f636c5db1 refactor(core): use string for DeepSeek model 2026-09-17 06:51:52 -07:00
Yujong Lee
cde34d2b39 fix(rust): decode Anthropic citation deltas
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-17 13:43:28 +00:00
Yujong Lee
85e70ea374 fix(ocr): await blocking preparation on cancellation 2026-09-16 20:49:31 -07:00
Yujong Lee
e0ce998091 fmt 2026-09-16 20:21:51 -07:00
Yujong Lee
edfa01da81 refactor(ocr): mirror Python provider layout and preserve tests 2026-09-16 19:48:26 -07:00
Yujong Lee
03cd00fbb1 refactor(rust): standardize messages errors
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-17 02:08:26 +00:00
Yujong Lee
4e5a9efd9d feat(rust): map anthropic messages transforms 2026-09-16 18:25:40 -07:00
Yujong Lee
2414d1f028 feat(rust): scaffold anthropic stream transformation 2026-09-16 18:10:28 -07:00
Yujong Lee
c621435ef7 refactor(ocr): move file preparation from the python bridge into litellm-core
Delete litellm/ocr/input.py and the native _ocr_file_document, _ocr_upload_document
and _ocr_mime_type helpers. File documents now project to a typed OcrDocumentInput
and the core lifecycle reads local paths, encodes bytes and asks the host to read
file-like objects through a ReadDocument operation before the provider request

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 21:02:30 +00:00
Yujong Lee
23633445d7 refactor(rust): extract auth and cache crates
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 18:12:11 +00:00
Yujong Lee
96baeb8b04 refactor(rust): remove gateway, config, router, realtime, and trace-parity infrastructure
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 16:00:07 +00:00
yujonglee
347b642bdd
refactor(ocr): complete native lifecycle and preserve Azure auth (#40734)
* refactor(ocr): extract call completion boundary

* fix(ocr): release completion state after dispatch

* test(ocr): prove wrapper completion handoff

* test(ocr): narrow mapped failure assertion

* fix(ocr): preserve wrapper invocation kwargs

* fix(ocr): retain completion through finalization

* fix(ocr): make completion ownership explicit

* refactor(ocr): resolve logging executor explicitly

* fix(callbacks): preserve completion lifecycle behavior

* refactor(ocr): move public OCR into native lifecycle

* refactor(ocr): remove unused rust bridge capability

* wip

* wip

* refactor

* wip

* fix(ocr): preserve reducto native compatibility

* wip

* fix(ocr): document native callable casts

* perf(ocr): bound responses and reduce native scheduling overhead

* refactor(python-bridge): organize placeholder routes

* refactor test

* fix(ocr): normalize DeepSeek document content

* perf(ocr): skip unused callback work and benchmark callback overhead

* fix(ocr): align conversion contracts

* test(ocr): cover official provider response shapes

* fix(ocr): restore Python fallback and honor Rust opt-out

* fixes and refactor

* fix(ocr): preserve Azure Document Intelligence authentication

* fix(rust): enforce OCR response limits and lint contracts

* test(rust): align native OCR contract coverage

* test(ocr): isolate Azure auth precedence coverage
2026-09-12 11:56:49 -07:00
yujonglee
83ab0113f0
feat(ocr): add Vertex DeepSeek adapter and remove legacy OCR pipeline (#40509)
* feat(ocr): add Vertex DeepSeek adapter

* fix(ocr): restore stacked CI coverage

* style(ocr): apply workspace rustfmt

* fix(ocr): deduplicate stacked gateway error mapping

* test(ocr): keep response format checks at dispatch

* fix(ocr): initialize gateway input provenance

* refactor(ocr): preserve DeepSeek extra params

* refactor(ocr): align Vertex DeepSeek preparation

* fix(gateway): drop removed OCR credential error variant

* fix(ocr): fail closed for deferred hooks and Vertex destinations

* fix(ocr): preserve DeepSeek credential provenance
2026-09-11 16:22:57 -07:00
yujonglee
b8928170e9
feat(ocr): add Vertex Mistral adapter (#40507)
* feat(ocr): add Vertex Mistral adapter

* test(ocr): validate Vertex credentials at adapter boundary

* refactor(ocr): preserve Vertex Mistral extra params

* refactor(ocr): align Vertex authentication lifecycle

* refactor(ocr): keep Vertex preparation behind bridge

* fix(ocr): protect Vertex credential destinations

* fix(auth): restrict request Vertex token endpoints
2026-09-11 16:22:56 -07:00
yujonglee
0dd5e6e289
feat(ocr): add Reducto legacy and v3 adapters (#40535)
* feat(ocr): add Reducto adapters

* fix(ocr): decline missing Reducto credentials

* fix(ocr): map Reducto credentials in gateway errors

* test(ocr): keep Reducto coverage at SDK boundary

* test(ocr): remove stale gateway Reducto cases

* fix(ocr): stop retaining Reducto responses by default

* refactor(ocr): preserve Reducto extra params

* refactor(ocr): adopt request preparation contract

* fix(ocr): preserve provider model passthrough

* fix(ocr): reject unknown Reducto models

* fix(ocr): preserve Reducto provider options
2026-09-11 16:22:56 -07:00
yujonglee
b544f2244b
feat(ocr): add Azure Document Intelligence adapter (#40534)
* feat(ocr): add Azure Document Intelligence

* fix(ocr): decline missing Document Intelligence credentials

* fix(ocr): map Document Intelligence credentials

* test(ocr): expose Azure transport to adapter tests

* fix(ocr): preserve native responses through Rust bridge

* feat(core): add URL query pair completion

* fix(ocr): declare Document Intelligence native responses

* fix(auth): preserve Azure credential provenance in OCR adapters

* refactor(ocr): use shared native response handling

* refactor(ocr): preserve Document Intelligence extra params

* refactor(ocr): adopt request preparation contract

* refactor(ocr): keep native response handling behind bridge

* fix(ocr): prevent credential-bearing polling redirects

* fix(ocr): update Azure auth imports

* fix(ocr): bound Document Intelligence polling rate

* fix(ocr): preserve proxy credential provenance

* test(ocr): assert native bridge format support
2026-09-11 16:22:55 -07:00