mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-21 05:15:06 +00:00
One trait per payload replaces CallHooks and its on_event bag: ArgumentHooks, ProviderHooks, ResponseHooks and OutcomeHooks over a Surface type bag. Transforms fold through the groups and stop on the first error, outcomes reach every group and only a Cancelled group stops the rest, so ChainRuntime, HookGroupAdapter, DynCallHooks and the runtime terminal match are gone. Hooks<S> composes mounted groups, request stages in mount order, response and terminal stages in reverse host-python keeps PythonSurface, the per-stage cancellation guard behind PythonSurface::group, and report_unless_cancelled as the one place an ordinary outcome error becomes unraisable. The legacy adapter implements each facet in its own file under facets/, which also lists the Python callbacks each stage reaches, and mapping.rs only collects them. SdkPolicy does its work in prepare, so the logging-before-policy ordering rule is no longer load-bearing
3.3 KiB
3.3 KiB
- Target invariants, not completion claims
- This crate owns compatibility for all existing Python callbacks and loggers, including
CustomLogger.facets/holdsLegacyHookson each facet of the call, one file per facet, each listing the Python callbacks its stages reach.mapping.rscollects those lists and the inventory of Python-owned hooks. A Python-owned entry records an existing path, never permission to invoke it a second time. The native call adapter preserves theLoggingcontract (function_setup, the deployment hooks,pre_call/post_call, the sync and async success and failure fan-out, the deferred proxy release, the argument sharing those callbacks rely on)- Smell test: if a future callback host (
callbacks-v1-python, WASM, in-process Rust) could share a piece of this crate, it does not belong here - SDK request policy (credential inheritance, the budget and retry-count limits) is a separate argument group supplied by
python-bridge - The driver in
litellm-host-python, the routes and core see onePythonGroup. They never learn which Python objects consume a call
- Smell test: if a future callback host (
- Every litellm Python internal Rust still borrows is a variant of
LegacyPython, grouped by subsystem, with its signature pinned inpython_contract.json- The enum only shrinks: when Rust owns a subsystem, delete its group rather than adding a Rust path beside it
- Calling a user's own callback directly is permanent Python surface and gets its own type outside
LegacyPython
PublicCallis the caller's call asLoggingsees it: the positional arguments, the keyword view as the call rewrites it (setup, deployment hook, preflight) and the bound request object backing omitted keywords. Shared bridge composition hands it toLegacyLogging. Routes use the neutral call boundaryLoggingOperationselects legacy logging entrypoints and response handling. It belongs here rather than in shared inference data contractssetupreuses aLoggingpassed aslitellm_logging_obj(the proxy and Router) and otherwise builds one throughfunction_setup. Which callbacks run isLogging's decision, never this crate's- Callbacks receive the caller's own objects and may mutate them. This crate alone carries that obligation
- Retain complete boundary arguments, opaque values, aliases, omitted/default distinctions and deliberate copies. Preserve the deployment-hook kwargs view
- Before
pre_call, re-alias every body key whose value equals the caller's argument to the caller's own object, resolved throughlitellm_host_python::lookup - Retain body/header roots from
pre_calltopost_call. In-place mutation reaches the wire, envelope field replacement is visible to later callbacks only
- Success and failure handlers receive the exact selected public response or exception
- A failure-handler error cannot suppress the other eligible family or replace the mapped provider error. A cancellation ends the call with no further dispatch
- Dispatch errors never replay provider work or trigger the opposite outcome. The proxy releases deferred success at most once
- Delivery follows the registry, not the callable's type: direct, awaited, executor-submitted, logging-worker and deferred paths stay distinct
- Traverse every retained Python edge.
closeis idempotent and restores the correlation context once