Commit graph

7 commits

Author SHA1 Message Date
devin-ai-integration[bot]
0b8817afbb
perf(bedrock): audio transcription via rust core (py->rust bridge) (#33990)
* feat(bedrock): add audio transcription via Converse with py->rust bridge

Co-Authored-By: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com>

* fix(ci): exclude rust transcription rollout flag from docs check

Co-Authored-By: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com>

* fix(bedrock): await rust/python fallback in async transcription dispatch

Co-Authored-By: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com>

* test(bedrock): cover audio transcription rust dispatch

Co-Authored-By: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com>

* refactor(bedrock): route audio transcription through rust

Co-Authored-By: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com>

* refactor(bedrock): move rust transcription dispatch out of main

Co-Authored-By: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com>

* test(bedrock): include rust transcription coverage shard

Co-Authored-By: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com>
2026-07-20 14:09:41 -07:00
devin-ai-integration[bot]
95332584fd
feat(rust): expose Anthropic Messages route (POST /v1/messages) on the axum gateway (#33880)
* feat(rust): expose anthropic messages route

Co-Authored-By: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com>

* fix(rust): use provider model for messages upstream

Co-Authored-By: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com>

* feat(rust): stream Anthropic Messages SSE on POST /v1/messages

Co-Authored-By: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com>

* test(rust): prove alias is substituted with provider model on /v1/messages

Co-Authored-By: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com>

* fix(rust): make anthropic messages provider constant available without server feature

Co-Authored-By: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com>
2026-07-19 01:41:37 +00:00
ishaan-berri
bdafc9a008
feat(ocr): thin Rust OCR Python bridge (#31368)
* feat(ocr): thin Rust OCR Python bridge

* refactor(rust): group provider routing helpers
2026-06-25 18:42:59 -07:00
ishaan-berri
62f93a3343
feat: add Rust OCR providers (#31272)
* feat: port OCR providers to Rust gateway

* chore(deps): update langgraph checkpoint lock

* ci: scope ruff format check to changed files

* ci: fix OCR lint and patch coverage

* fix(ocr): block mapped IPv6 fetch targets

* test(ocr): include rust bridge coverage in OCR shard

* ci: rerun responses shard
2026-06-25 15:12:30 -07:00
ishaan-berri
4efce809d0
feat(proxy): add POST /v1/callbacks/logs to replay logging payloads through callbacks (#31134)
* feat(proxy): add logging_endpoints package init

* feat(proxy): add POST /v1/callbacks/logs to replay logging payloads through the success/failure callback fan-out

* feat(proxy): register callback_logs_router

* test(proxy): add logging_endpoints test package init

* test(proxy): cover /v1/callbacks/logs replay, admin guard, and partial-failure handling

* refactor(proxy): move callback-logs request/response models to litellm/types/proxy

* refactor(proxy): wrap callback-logs replay in CallbackLogsReplayer class with payload logging

* test(proxy): update callback-logs tests for class-based replayer and separated types

* fix(proxy): cover /v1/callbacks/ in backend component allowlist

The new /v1/callbacks/logs route was dropped by both component
allowlists, failing test_gateway_plus_backend_covers_full_app. It's an
admin-only spend-logging route, so it belongs on the backend (control
plane) alongside the existing /callbacks family.

* refactor(proxy): use builtin dict/list generics in callback-logs endpoint

Switch Dict/List from typing to builtin dict/list to satisfy the ruff
strict-rule budget (UP006).

* refactor(proxy): use builtin dict/list generics in callback-logs types

UP006: builtin generics over typing.Dict/List.

* chore(ui): regenerate schema.d.ts for /v1/callbacks/logs

Run npm run gen:api to add the CallbackLogRecord/CallbackLogsRequest/
CallbackLogsResponse types and the /v1/callbacks/logs path, keeping the
dashboard types in sync with the proxy OpenAPI spec.

* fix(proxy): force stream=False when replaying callback logs

A replayed StandardLoggingPayload is a terminal, fully-aggregated event —
the producer (e.g. the rust realtime gateway) already collected the whole
session before POSTing. Marking the rebuilt Logging object as streaming made
async_success_handler wait for a complete_streaming_response that never
arrives, so the spend log was never written. Realtime sessions now land in
LiteLLM_SpendLogs.

* feat(litellm-rust): CustomLogger callback layer posting to /v1/callbacks/logs

integrations/ mirrors litellm/integrations/: a sync, typed CustomLogger trait
(base contract), a typed StandardLoggingPayload, and LiteLLMPythonProxyAPILogger
— the first concrete logger, owning a bounded channel + background worker that
batches and POSTs to the Python proxy's /v1/callbacks/logs.

* feat(litellm-rust): RealTimeStreaming per-session log collector

1:1 with Python's RealTimeStreaming: observe() accumulates O(1) usage/model/id
per event (never buffers frames); log_messages() builds one StandardLoggingPayload
on session close and fans out to the CustomLogger callbacks. request_id == the
OpenAI realtime session id (sess_…), with the gateway id as fallback.

* feat(litellm-rust): wire realtime logging into the splice (lock-free observe)

The collector is owned on the splice task and observed via a synchronous &mut
callback threaded through providers::realtime::realtime() — no Arc/Mutex/atomic
on the per-frame hot path. On session close the bridge flushes one payload.
AppState carries the registered loggers; main spawns the proxy logger.

* docs(litellm-rust): ai-gateway realtime logging architecture

* docs(litellm-rust): document request-log egress to the LiteLLM control plane

Add a 'Request logging' guide to the ai-gateway README: how to point the gateway
at a LiteLLM proxy via LITELLM_PROXY_BASE_URL (+ LITELLM_MASTER_KEY for the
admin-only /v1/callbacks/logs POST), and the non-blocking / one-payload-per-session
behavior.

* feat(litellm-rust): make log-egress tunables env-overridable

Channel capacity, batch size, and flush interval now read from
LITELLM_LOG_CHANNEL_CAPACITY / LITELLM_LOG_BATCH_SIZE / LITELLM_LOG_FLUSH_INTERVAL_MS,
falling back to the DEFAULT_* consts on missing/invalid/non-positive values.
Grouped behind an EgressTunables::from_env() read once at logger construction.

* docs(litellm-rust): document log-egress tuning env vars

* docs(litellm-rust): require constants in a crate-level constants.rs

Mirror of Python's litellm/constants.py rule — magic numbers and fixed strings
go in src/constants.rs, not inline in feature modules; env-overridable tunables
keep their DEFAULT_* value there.

* refactor(litellm-rust): move ai-gateway constants into constants.rs

Per the new rule: the log-egress defaults (proxy base, ingest path, channel
capacity, batch size, flush interval) and the realtime provider default move to
crates/ai-gateway/src/constants.rs; modules import from it.

* ci: run logging_endpoints tests in the proxy-infra coverage shard

tests/test_litellm/proxy/logging_endpoints wasn't in any coverage-uploading
job, so callback_logs_endpoints.py showed only import-level coverage (~35%) on
codecov/patch despite being ~98% covered locally. Add it to proxy-infra's
test-path so the test is exercised under --cov.

* fix(litellm-rust): hash the master key before logging — never send the raw credential

Greptile/Veria P1: user_api_key_hash was the plaintext LITELLM_MASTER_KEY, which
fans out to spend logs and every callback (Langfuse/Datadog) and could be
recovered from logs. SHA-256 it (auth::hash_token, matching the proxy's
hash_token); the field is named *_hash and the proxy stores it verbatim when it
isn't sk-prefixed, so the DB value is identical with zero plaintext exposure.

* fix(litellm-rust): observe realtime logging on upstream events only

Greptile P1: observe ran on the client->upstream arm too, so an authenticated
client could send a fabricated response.done and inflate its own spend log.
session.created/response.done are server->client events; observe the upstream
arm only.

* feat(proxy): bound callback-logs batch + return per-record failures

Greptile P2: cap /v1/callbacks/logs at MAX_CALLBACK_LOG_RECORDS (default 1000,
env-overridable) so one POST can't trigger an unbounded callback/DB fan-out; and
return per-record {index, error} failures so a caller (the rust gateway) can
distinguish a transient callback error from a structurally bad payload.

* chore(ui): regenerate schema.d.ts for CallbackLogFailure / failures field

* fix(constants): make MAX_CALLBACK_LOG_RECORDS a plain constant

It doesn't need to be env-configurable (only the rust egress tunables are). As an
os.getenv var it tripped tests/documentation_tests/test_env_keys.py, which requires
every env key to be documented in the (separate-repo) config_settings.md. Plain
constant → not scanned → code-quality + documentation checks pass.

* docs(litellm-rust): trim ai-gateway ARCHITECTURE.md to one diagram + notes

* docs(litellm-rust): tighten the README request-logging section

* docs(litellm-rust): ARCHITECTURE.md is just the diagram (gateway = inference, spend = callback)

* docs(litellm-rust): drop em-dashes from the request-logging section

---------

Co-authored-by: Ishaan Jaffer <ishaanjaffer0324@gmail.com>
2026-06-24 15:25:10 -07:00
ishaan-berri
bd759182ca
refactor(litellm-rust): dissolve providers into core + ai-gateway (strict 3-crate layers) (#31218)
* refactor(litellm-rust): move provider transforms into litellm-core + crate allowlist test

* feat(litellm-rust): ai-gateway absorbs route I/O (io/) with lib+server feature split

* refactor(litellm-rust): point python-bridge at litellm-ai-gateway

* build(litellm-rust): macOS pyo3 dynamic_lookup linker flag for cdylib builds

* docs(litellm-rust): 3-crate map in README/AGENTS + refresh CLAUDE boundary

* refactor(litellm-rust): update workspace members to the three crates
2026-06-24 12:22:43 -07:00
ishaan-berri
1d5ab42e14
feat: add minimal rust router + axum ai-gateway calling router.realtime (2/2) (#31135)
* add CoreError::Routing variant for deployment selection failures

* add minimal Rust Router (simple-shuffle) mirroring router.py spec

* add litellm-router crate manifest

* add ai-gateway POST /v1/realtime handler calling router.realtime

* add ai-gateway health routes

* wire ai-gateway routes into the axum app

* add ai-gateway AppState holding the shared router

* add ai-gateway axum server entrypoint

* add litellm-ai-gateway binary crate manifest

* docs: add ai-gateway folder-architecture AGENTS.md

* register router + ai-gateway crates and axum/rand deps in workspace

* update Cargo.lock for router + ai-gateway crates

* split router: extract model_list types into deployment module

* split router: extract routing policy into strategy module

* split router: move Router orchestration into router module

* router lib: wire submodules and re-export public API

* add read_model_list helper reusing ProxyConfig env/secret resolution

* add GIL-activity tracker (records acquisitions, 30s window)

* add GET /health/gil endpoint for polling GIL activity

* add pyo3 load_router_from_config bridge (feature-gated, load-time only)

* register /health/gil route in ai-gateway

* wire build_router: load from python config when feature enabled

* add optional pyo3 dep + python-config feature to ai-gateway

* update Cargo.lock for optional pyo3 dependency

* fix: satisfy strict ruff budget (FA100) in read_model_list

* test: cover read_model_list env resolution + empty config

* ai-gateway: bind localhost by default, warn on bad PORT/missing keys, wire gateway key

* ai-gateway: add gateway_key to AppState for realtime auth

* ai-gateway: require bearer auth + map unknown model to 404 on /v1/realtime

* ai-gateway: move python interop into python/ with load-time-only AGENTS.md

* ai-gateway: document auth, gil, and python folder in AGENTS.md

* core: add router module (model_list types + simple-shuffle selection)

* ai-gateway: dispatch realtime via core router + providers (drop router crate dep)

* update Cargo.lock: fold router into core

* workspace: drop crates/router member and litellm-router dep

* read_model_list: reuse ProxyConfig.get_config (includes + os.environ + DB) instead of thin yaml read

* ai-gateway: constant-time bearer compare + 500 (not 503) for unconfigured key

* ai-gateway: trim stored gateway key to match trimmed bearer token

* ai-gateway: add subtle dep for constant-time comparison

* workspace: add subtle dependency

* update Cargo.lock for subtle

* core router: make strategy a folder (one module per strategy, simple_shuffle)

* providers: make realtime() a streaming splice (client stream <-> OpenAI) instead of collect

* providers: add futures-channel dev-dep for the streaming live test

* ai-gateway: make /v1/realtime a WebSocket (auth before upgrade, splice typed events)

* ai-gateway: dispatch realtime as a stream splice

* ai-gateway: route /v1/realtime via GET (WebSocket), drop POST

* ai-gateway: enable axum ws feature + futures-util

* update Cargo.lock for ws feature + futures-channel

* core router: add has_deployment() for pre-flight model checks

* ai-gateway: extract auth into auth/ module (single master key, LITELLM_MASTER_KEY)

* ai-gateway routes: adopt router()-per-module template + merge in app()

* ai-gateway: document auth/ + routes template in AGENTS.md

* ai-gateway: realtime route as thin handler + service + transport

* ai-gateway: auth as a RequireMasterKey extractor (idiomatic axum FromRequestParts)

* ai-gateway: docs for auth extractor + simplified route template

* ai-gateway: collapse realtime route to mod.rs + service.rs; docs for extractor/template

* providers realtime: enforce idle timeout around the splice (reap stalled sessions)

* ai-gateway: rename realtime service timeout param to idle_timeout

---------

Co-authored-by: Ishaan Jaffer <ishaanjaffer0324@gmail.com>
2026-06-23 19:16:34 -07:00