Commit graph

130 commits

Author SHA1 Message Date
Yujong Lee
bf7d1c0733 chore: consolidate CLAUDE.md into AGENTS.md
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-19 02:30:35 +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
c2679757b3 refactor(rust): put stream billing on the legacy surface 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
4627ec4ea8 test(rust): cover post-call header identity
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-18 15:43:08 -07:00
Yujong Lee
dd2e6c17bc fix(rust): preserve OCR callback headers
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-18 15:43:08 -07:00
Yujong Lee
30f7b8442b chore(rust): lock proptest 2026-09-18 15:43:08 -07:00
Yujong Lee
a737e3430a test(rust): property and parametrized tests for legacy callback contracts
The payload boundary of callbacks-legacy gets a model-based proptest: for any
JSON body, caller keywords and callback edit, keywords the route sends unchanged
reach pre_call as the caller's own objects, and the wire is the body pre_call
received as the callback left it. A parametrized test pins that a keyword the
bridge never reads keeps its identity through setup, the deployment hook,
check_limits and prepare.

Behaviour owned by the real Logging object is pinned end to end in the OCR
tests: a hypothesis version of the body property over HTTP, sync hooks seeing no
running event loop, retained payloads staying intact after the call, success
callbacks sharing one standard logging payload, and state stashed before a
blocking deployment hook raises reaching both failure callback families
2026-09-18 15:43: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
9d134413c9 test(rust): rename the standalone 429 test to match the rule 2026-09-18 14:01:09 -07:00
Yujong Lee
836bf7d897 refactor(rust): make the exception mapper a pure rule table
Rebuild exception_type around text rules per provider family and one shared
status table. The mapper takes the context, an injected redactor and the
original failure, and returns a PublicError with the message, the real
upstream response and the debug text. Every divergence from the Python
mapper and every known gap is listed in the module header

Match Python on a standalone 429 with an unknown status and on Cohere's
rules for failures without a status. Drop python_repr and the unread
public_failures fixtures
2026-09-18 13:59:36 -07:00
Yujong Lee
0f59e61f24 fix(rust): align exception mapping tests with Python
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-18 20:17:11 +00:00
Yujong Lee
657cf18aea feat(rust): port exception_type to litellm-core-utils
Adds a Rust port of litellm_core_utils/exception_mapping_utils.exception_type
with its provider rule tables (OpenAI-compatible, Cohere, Vertex AI), the
secret redaction patterns from secret_redaction.py, and a Python repr helper
for messages that quote caller values.

The public failure shapes are pinned by golden JSON fixtures under
tests/test_litellm/rust_bridge/fixtures/public_failures, which the Python
side reads too once the bridge is wired to this module. Nothing calls the
port yet.
2026-09-18 13:01:55 -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
1f0c10147d merge: port OCR request validation and upstream error mapping onto main's dispatch layout
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-17 18:33:20 +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
b26935416a Merge remote-tracking branch 'github/main' into litellm_rust_bridge_declarative_route_catalog
# Conflicts:
#	tests/e2e/access_control/test_model_access_group_e2e.py
2026-09-17 11:08:08 -07:00
Yujong Lee
4ecc55ec70 fix(ocr): build upstream httpx response in Python and satisfy PT012
The Rust bridge imported httpx to construct the provider error response, which
fails in the isolated wheel check where httpx is absent. Rust now raises
RustUpstreamError with a headers attribute and the Python lifecycle wraps it in
a typed UpstreamFailure carrying the httpx.Response before legacy mapping.
Test helpers gained call_native so pytest.raises blocks hold a single call

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-17 17:34:18 +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
1ef094bb41 feat(rust): add standalone framing crate
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-17 00:30:43 +00:00
Yujong Lee
93ba409adf fix(rust): address Redis cache review findings
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 23:19:28 +00:00
Yujong Lee
0b3c3885bc fix(rust): scope Redis dependency to cache crate
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 23:15:00 +00:00
Yujong Lee
8ae1f76339 feat(rust): scaffold redis cache crate
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 23:15:00 +00:00
Yujong Lee
3de23e7f18 test(rust_bridge): drop generated OCR route assertions from bridge_route tests
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 23:10:10 +00:00
Yujong Lee
c635399f6e merge: origin/main into litellm_rust_bridge_declarative_route_catalog
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 22:54:51 +00:00
Yujong Lee
64cd6538a6 cleanup 2026-09-16 14:16:15 -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