Commit graph

10107 commits

Author SHA1 Message Date
user
4d92bc8b86
fix(vector-stores): re-raise HTTPException from get_vector_store_info; allowlist recursion
Two issues from the previous push's review:

1. **Greptile P1**: ``get_vector_store_info`` had the same catch-all
   ``except Exception`` pattern as ``update_vector_store``, so the
   HTTPException(403/404) raised by both the in-memory access check and
   the new ``_fetch_and_authorize_vector_store`` helper was rewritten as
   500. Mirror the ``except HTTPException: raise`` guard from
   ``update_vector_store``.

2. **code-quality CI** (``tests/code_coverage_tests/recursive_detector.py``)
   flagged ``_redact_sensitive_litellm_params`` as an unallowlisted
   recursive function. Match the convention of other allowlisted
   helpers ("max depth set"): bound recursion at depth 10 (well above
   any plausible nesting level for real ``litellm_params`` payloads),
   return the redaction sentinel on overflow, and add the function
   name to ``IGNORE_FUNCTIONS``.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 18:56:55 +00:00
user
294ac8383e
fix(vector-stores): recurse into nested litellm_params; handle JSON-string shape
Three issues surfaced in review of the previous commit:

1. **Veria — Medium**: ``litellm_params`` carries a nested
   ``litellm_embedding_config`` dict (auto-resolved from the model
   registry on create / update) which itself holds ``api_key`` /
   ``aws_*`` / ``vertex_credentials``. The previous redactor only
   inspected top-level keys, so the nested values passed through
   unredacted. Recurse into nested dicts.

2. **Greptile — P2**: when ``litellm_params`` is a JSON-serialized
   string (the in-memory registry occasionally stores it that way), the
   previous redactor silently no-op'd via the ``isinstance(..., dict)``
   guard and echoed the raw payload back. Now: parse, redact, re-serialize.
   If the string is not valid JSON, replace it with the redaction
   sentinel rather than echo it.

3. **mypy** flagged ``_redact_sensitive_litellm_params``'s
   ``Optional[Dict[str, Any]]`` signature as incompatible with the
   ``object``-typed call site. Widened to ``Any -> Any`` to reflect the
   actual contract (the function now handles dict / str / None / other).

Also fixes a related test regression in
``test_remove_sensitive_info_from_deployment_with_excluded_keys``: the
``"credentials"`` plural addition to ``SensitiveDataMasker`` defaults
caused the first call (without ``excluded_keys``) to mutate the input
dict's ``litellm_credentials_name`` to a masked value. The second call
(with ``excluded_keys``) then saw the already-masked value rather than
the original. Construct fresh input for each call.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 18:56:40 +00:00
user
51d560ba2e
chore(vector-stores): also gate /vector_store/update; upstream credentials plural in masker
Two architectural extensions to the credential-redaction in the previous
commit:

1. ``/vector_store/update`` had two gaps:
   - No per-store access control. Any authenticated principal that
     passed the premium-feature gate could mutate *any* vector store,
     including stores belonging to other teams.
   - The response returned the full DB row including ``litellm_params``,
     so the caller could read another team's persisted provider
     credentials by submitting a no-op metadata change.
   Mirror the access-control check ``/vector_store/info`` already
   performs (``_check_vector_store_access`` against the existing row),
   redact ``litellm_params`` in the response, and add an
   ``except HTTPException: raise`` guard so the 403/404 responses don't
   get rewritten as 500 by the catch-all.

2. ``SensitiveDataMasker``'s default ``sensitive_patterns`` set used
   segment-exact matching, so ``credential`` matched ``vertex_credential``
   but not ``vertex_credentials`` (the actual Vertex field name). The
   previous commit worked around this with a per-call extension; this
   commit puts the plural in the upstream defaults so every caller
   (Redis config dump, MCP debug headers, cache routes, ...) gets the
   correct behavior. The local override in
   ``vector_store_endpoints/management_endpoints.py`` is removed.

Also updates ``test_excluded_keys_exact_match`` which relied on
``credentials`` *not* being a sensitive pattern to demonstrate
case-sensitive ``excluded_keys`` matching. The intent of the test
(case-sensitive match) is preserved; the assertion now reflects that
when ``excluded_keys`` fails to apply (wrong case), the field falls
through to standard pattern-based masking instead of being passed
through unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 18:56:09 +00:00
user
a99943ec49
test+style: drop _redact_vector_store wrapper; inherit masker defaults
/simplify pass:
- Remove the single-call-site ``_redact_vector_store`` wrapper. Inline
  the two-line redaction at its only caller in ``list_vector_stores``;
  ``get_vector_store_info`` was already calling the inner helper directly.
- Inherit ``SensitiveDataMasker``'s default sensitive-key set instead of
  duplicating the 12-element list, then add only the plural
  ``credentials`` extension. Won't drift if upstream defaults change.
- Trim the over-explained docstring on ``_redact_sensitive_litellm_params``
  to a one-paragraph summary; the WHY (credential-leakage class) belongs
  in the commit message, not in every consumer's IDE tooltip.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 18:55:40 +00:00
user
0806cca340
chore(vector-stores): redact credentials from list/info responses
``LiteLLM_ManagedVectorStore.litellm_params`` carries the upstream provider
credential — OpenAI ``api_key``, AWS ``aws_access_key_id`` /
``aws_secret_access_key``, GCP ``vertex_credentials``, etc. ``GET
/vector_store/list`` and ``POST /vector_store/info`` return these
verbatim to any authenticated principal. Because both routes are in
``openai_routes``, ``RouteChecks.is_llm_api_route`` short-circuits the
standard role gate, so even read-only users and narrowly-scoped keys can
read every stored credential.

Replace credential-bearing values with the ``REDACTED_BY_LITELM``
sentinel in both responses while preserving non-secret keys
(``api_base``, ``region``, ``model``, ``api_version``) so callers can
still see *which* upstream is configured. Detection reuses
``SensitiveDataMasker.is_sensitive_key`` with the default heuristics
plus the plural ``credentials`` pattern (covers Vertex's
``vertex_credentials`` field, which the singular ``credential`` pattern
misses on segment-exact matching).

Applied at:
- ``list_vector_stores`` (``GET /vector_store/list``,
  ``GET /v1/vector_store/list``)
- ``get_vector_store_info`` (``POST /vector_store/info``), both the
  in-memory-registry path and the prisma-DB fallback

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 18:55:40 +00:00
user
bdb00c43cf
fix(spend-tracking): drop orphaned imports; align tests with alias contract
CI surfaced two issues from the previous commit:

1. ``general_settings`` and ``master_key`` were still imported at the top
   of ``get_logging_payload`` but had no remaining users after the
   master-key hash-detection blocks were removed. Drop the import.

2. ``tests/proxy_unit_tests/test_user_api_key_auth.py::test_x_litellm_api_key``
   and ``tests/proxy_unit_tests/test_key_generate_prisma.py::test_master_key_hashing``
   asserted ``valid_token.token == hash_token(master_key)`` — the
   pre-alias behavior. The new contract is
   ``valid_token.token == LITELLM_PROXY_MASTER_KEY_ALIAS`` (and !=
   ``hash_token(master_key)``), since the master key (and its hash)
   must not propagate to the verification-token column or any other
   downstream consumer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 18:53:12 +00:00
user
9d9f09934e
chore(auth): substitute alias for master key on UserAPIKeyAuth
Two related changes to how the master-key auth path interacts with
downstream consumers of UserAPIKeyAuth.api_key:

1. The master-key auth branch in user_api_key_auth.py now sets
   `valid_token.api_key` to a stable alias
   (`LITELLM_PROXY_MASTER_KEY_ALIAS = "litellm_proxy_master_key"`) instead
   of the raw master key. Downstream consumers — spend logging,
   Prometheus metrics, audit trails, rate limiting, cost tracking — now
   receive the alias instead of the master key (which they would
   previously hash and propagate). Neither the raw master key nor its
   hash flows past the auth layer.

2. `_is_master_key` in spend_tracking_utils.py is reduced to a strict
   raw-only constant-time comparison. The hashed form is no longer
   considered equivalent.

Side effects:

- The two hash-detection blocks in `get_logging_payload` are removed.
  They were re-detecting the master key per spend-log write to swap in
  the alias; that detection happens once at the auth layer now.

- The `disable_adding_master_key_hash_to_db` general setting becomes a
  no-op. Operators can remove it from their config; existing config is
  still accepted.

- Operator dashboards that filter Prometheus metrics by the master-key
  hash will need to switch to the `api_key="litellm_proxy_master_key"`
  label.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 18:53:12 +00:00
Michael Riad Zaky
04687ba48e Trim verbose comments and docstrings 2026-04-29 11:07:35 -07:00
Michael Riad Zaky
2b9ad4d4eb Fall through to team default when per-member budget max_budget is NULL 2026-04-29 10:14:09 -07:00
Yassin Kortam
9b3cd5ca25
Merge pull request #26730 from yassinkortam/fix/http-handler-keepalive
fix: add optional TCP SO_KEEPALIVE support to aiohttp's TCPConnector
2026-04-29 10:10:59 -07:00
Yassin Kortam
848b79acb5 fix: added keepalive args for aiohttp tcpconnector 2026-04-29 09:14:57 -07:00
Sameer Kankute
d8d1444da4
Merge pull request #26710 from minznerjosh/fix/bedrock-anthropic-tool-result-pdf-content
fix(bedrock, anthropic): translate OpenAI file content on tool-result path
2026-04-29 12:59:08 +05:30
Sameer Kankute
8af338a202
Merge pull request #26757 from BerriAI/litellm_internal_staging
merge main
2026-04-29 12:44:09 +05:30
Sameer Kankute
4b03cb68a2
feat(proxy): move search tool access to object permissions
Store search tool allowlists only on object permissions, wire auth/management/UI flows to object_permission.search_tools, and remove legacy team-metadata search credential code and tests.

Made-with: Cursor
2026-04-29 12:29:20 +05:30
Yuneng Jiang
aa2ef41200 fix(proxy): preserve original transport error if reconnect itself raises
Greptile review on #26756 (P2): if `attempt_db_reconnect` itself raises
(e.g. lock cancellation, timer error, unexpected internal failure), the
original `httpx.ReadError` / transport error was lost — `failure_handler`
and `db_exceptions` alerts then logged the reconnect exception instead of
the actual DB transport problem, masking the root cause.

Wrap the reconnect call in a try/except. On reconnect failure, re-raise
the *original* `first_exc` and chain the reconnect error as `__cause__`
so it remains visible for debuggability without becoming the primary
exception observers see.

Adds `test_call_with_db_reconnect_retry_preserves_original_error_when_reconnect_raises`
asserting (a) the propagated exception is the original transport error
and (b) the reconnect exception is attached as `__cause__`.
2026-04-28 23:55:46 -07:00
Yuneng Jiang
1c9c219a74 fix(proxy): self-heal Prisma read paths + harden reconnect state machine
Two related fixes layered on top of the existing reconnect plumbing:

1. Restore reconnect-and-retry on `PrismaClient.get_generic_data` (issue
   #25143). 1.83.x lost the transport-reconnect-and-retry-once branch that
   1.82.6 had on this method, so transient `httpx.ReadError` flaps now
   surface immediately as `db_exceptions` alerts. `_update_config_from_db`
   fans out four concurrent `get_generic_data` reads, so a single transport
   blip used to mark four alerts and a stale config window.

   Adds `call_with_db_reconnect_retry` to `litellm/proxy/db/exception_handler.py`
   — a single canonical "try DB read, on transport error reconnect once and
   retry once" wrapper. Mirrors the inline pattern in
   `auth_checks._fetch_key_object_from_db_with_reconnect` so we have one
   implementation rather than three drifting copies, and gives future read
   paths a clean opt-in.

2. Fix the `_engine_confirmed_dead` flag-reset bug in
   `_run_reconnect_cycle`. The flag was cleared before `_do_heavy_reconnect()`
   ran, so any failure inside the heavy reconnect (timeout, missing
   DATABASE_URL, recreate failure) left the flag False — and the next
   attempt could silently demote to the lightweight path even though the
   engine was genuinely dead. Move the reset into the success branch so the
   flag stays True across heavy-reconnect failures and the next attempt
   re-enters the heavy branch.

Tests:

- `tests/test_litellm/proxy/db/test_exception_handler_reconnect_retry.py`
  (new) — 9 tests covering the helper's contract: happy path, retry on
  transport error, no retry on data-layer errors, propagation when reconnect
  fails, propagation after second transport error, `hasattr` guard for
  partial mocks, fresh-coroutine-per-call invariant, explicit timeout
  override, default timeouts read off the prisma_client.
- `tests/test_litellm/proxy/db/test_prisma_self_heal.py` — adds:
  - `test_get_generic_data_retries_on_transport_error_for_config_table`
  - `test_get_generic_data_propagates_when_reconnect_fails`
  - `test_engine_confirmed_dead_persists_across_failed_heavy_reconnect`
    (regression test for the flag-reset bug).

All 16 self-heal tests + 9 helper tests + 535 auth/exception-handler tests
pass locally.
2026-04-28 23:44:34 -07:00
Yuneng Jiang
8c91c8b2c4 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_dbReconnectNonBlocking 2026-04-28 23:29:36 -07:00
Cursor Agent
3fb5056305
fix(mcp): address greptile review on short tool prefix
- server.py: drop the redundant server_id append in
  _get_filtered_mcp_servers_from_mcp_server_names. iter_known_server_prefixes
  already yields server_id unconditionally, so the manual append (and its
  misleading comment) was a no-op duplicate.
- utils.py: rewrite the SHORT_MCP_TOOL_PREFIX docstring to accurately
  describe the collision behaviour. The previous wording said collisions
  were 'cosmetic only', but a natural-hash collision IS a routing-correctness
  issue, which is precisely why we already added _assign_unique_short_prefix
  to rehash deterministically. The new comment cross-references that path.
- utils.py: restrict the first character of the short prefix to [A-Za-z]
  via a 52-char alphabet for position 0 only. The remaining two positions
  still use the full base62 alphabet. This keeps prefixes valid identifiers
  on every backend and gives 52*62*62 = 199_888 distinct prefixes (still
  comfortably more than any realistic deployment).
- tests: add coverage proving the first character of the prefix is always
  alphabetic across many server_ids and rehash attempts.

Co-authored-by: Mateo Wang <mateo-berri@users.noreply.github.com>
2026-04-29 03:59:40 +00:00
Sameer Kankute
d7862e7fe8
Merge pull request #26745 from BerriAI/litellm_internal_staging
Some checks failed
Unit Tests: Caching (Redis) / caching-redis (push) Has been cancelled
Unit Tests: Proxy DB Operations / assert-shard-coverage (push) Has been cancelled
Unit Tests: Security / security (push) Has been cancelled
Unit Tests: Proxy DB Operations / auth-checks (push) Has been cancelled
Unit Tests: Proxy DB Operations / budgets (push) Has been cancelled
Unit Tests: Proxy DB Operations / custom-logging (push) Has been cancelled
Unit Tests: Proxy DB Operations / db-and-spend (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-runtime (push) Has been cancelled
Unit Tests: Proxy DB Operations / endpoints-and-responses (push) Has been cancelled
Unit Tests: Proxy DB Operations / guardrails-hooks (push) Has been cancelled
Unit Tests: Proxy DB Operations / jwt-and-keys (push) Has been cancelled
Unit Tests: Proxy DB Operations / key-generation (push) Has been cancelled
Unit Tests: Proxy DB Operations / logging-misc (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-server-core (push) Has been cancelled
Unit Tests: Proxy DB Operations / schema-migration (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-utils (push) Has been cancelled
merge mian
2026-04-29 09:25:42 +05:30
Sameer Kankute
af5b7be51d
Merge pull request #26742 from BerriAI/litellm_internal_staging
merge main
2026-04-29 09:20:12 +05:30
Cursor Agent
3215874e40
fix(test): scope ERROR log assertion to LiteLLM logger in test_model_alias_map
The test was flaking on unrelated asyncio ERROR records (e.g. "Unclosed
client session" from background tasks in other tests). Restrict the
assertion to records emitted by LiteLLM loggers so the test only fails
on errors actually produced by the code under test.

Co-authored-by: Mateo Wang <mateo-berri@users.noreply.github.com>
2026-04-29 03:48:41 +00:00
Cursor Agent
df3dbd18d6
feat(mcp): rehash short tool prefix on collision and cache per server
Two MCP servers can natural-hash to the same three-character base62
prefix. With 62**3 = 238_328 slots the birthday bound is ~488 servers
for 50% collision probability, so a single proxy hosting more than
~100 MCP servers has a non-trivial chance of seeing a collision in
practice — and a collision means tool names from two different servers
share a routing key, causing silent mis-routing.

Mitigation:

- compute_short_server_prefix(server_id, attempt=N) folds an attempt
  counter into the SHA-256 seed, so rehashes are deterministic and
  produce a fresh three-char prefix space per attempt.
- New MCPServer.short_prefix field caches the resolved (post-dedup)
  prefix on the model so it stays stable across the process lifetime.
- MCPServerManager._assign_unique_short_prefix walks attempts 0..N
  until it finds a prefix not already used by another server in the
  combined registry. Logs an INFO line when a rehash happens so
  operators have a breadcrumb if it ever does.
- Wired into every registration path: load_servers_from_config,
  add_server, update_server, reload_servers_from_database. The
  database reload path also carries the previously-resolved prefix
  forward so reloads don't churn it.
- get_server_prefix prefers the cached short_prefix when set, so the
  resolved value (not the raw natural hash) is used everywhere.
- iter_known_server_prefixes yields the cached short_prefix too, so
  reverse-lookup tolerance covers the rehashed form.

No-op when LITELLM_USE_SHORT_MCP_TOOL_PREFIX is disabled — the field
stays None and behaviour is unchanged.

Co-authored-by: Mateo Wang <mateo-berri@users.noreply.github.com>
2026-04-29 03:43:34 +00:00
Sameer Kankute
b516120036
Merge pull request #26737 from BerriAI/litellm_internal_staging
merge internal staging
2026-04-29 08:50:12 +05:30
ishaan-berri
4ae2996f08
Add gpt-image-2 support (#26644) (#26705)
* Add gpt-image-2 support

* Address gpt-image-2 PR feedback

Co-authored-by: Emerson Gomes <emerson.gomes@thalesgroup.com>
2026-04-28 20:10:42 -07:00
Sameer Kankute
cf74f55b79
Fix extra body error 2026-04-29 08:34:31 +05:30
Cursor Agent
fc49c181bc
feat(mcp): opt-in short-ID tool prefix to stay under 60-char tool name limit
Adds LITELLM_USE_SHORT_MCP_TOOL_PREFIX. When enabled, tool / prompt /
resource / resource-template names emitted from MCP servers are prefixed
with a deterministic three-character base62 ID derived from the server's
server_id (SHA-256 → base62) instead of the (potentially long)
alias / server_name. This keeps namespaced tool names well under the
60-character upper bound enforced by some model APIs while still letting
us distinguish MCP-routed tools from local tools.

Behavioural notes:

- Default off — when the env var is unset, the long-prefix behaviour
  is unchanged. The plan is to flip the default in a future release
  and remove the gate after a deprecation window.
- Prefix derivation is deterministic, so it is stable across processes,
  workers and restarts without any persistence layer.
- Reverse-lookup is tolerant: _create_prefixed_tools registers every
  known prefix form (alias / server_name / server_id / short ID) in
  the routing map and _get_mcp_server_from_tool_name resolves any of
  them. Old clients holding cached long-prefixed names continue to
  route correctly even after the flag is enabled.
- _get_allowed_mcp_servers_from_mcp_server_names accepts the short
  prefix in /mcp/{server_name}-style URLs.
- The OpenAPI tool-listing path now filters by the active server
  prefix instead of server.name so spec-backed servers benefit too.

Co-authored-by: Mateo Wang <mateo-berri@users.noreply.github.com>
2026-04-29 01:41:24 +00:00
Michael Riad Zaky
b07e1c0341 drop response body from vertex/bedrock transformation errors
Some checks failed
Unit Tests: Security / security (push) Has been cancelled
Unit Tests: Caching (Redis) / caching-redis (push) Has been cancelled
Unit Tests: Proxy DB Operations / assert-shard-coverage (push) Has been cancelled
Unit Tests: Proxy DB Operations / auth-checks (push) Has been cancelled
Unit Tests: Proxy DB Operations / budgets (push) Has been cancelled
Unit Tests: Proxy DB Operations / custom-logging (push) Has been cancelled
Unit Tests: Proxy DB Operations / db-and-spend (push) Has been cancelled
Unit Tests: Proxy DB Operations / endpoints-and-responses (push) Has been cancelled
Unit Tests: Proxy DB Operations / guardrails-hooks (push) Has been cancelled
Unit Tests: Proxy DB Operations / jwt-and-keys (push) Has been cancelled
Unit Tests: Proxy DB Operations / key-generation (push) Has been cancelled
Unit Tests: Proxy DB Operations / logging-misc (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-runtime (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-server-core (push) Has been cancelled
Unit Tests: Proxy DB Operations / schema-migration (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-utils (push) Has been cancelled
2026-04-28 17:38:42 -07:00
harish-berri
1d62ca0e23
Merge branch 'litellm_internal_staging' into litellm_token_verification_query_opt 2026-04-28 17:34:17 -07:00
Krrish Dholakia
fd32f29e39
Revert "lazy-load optional feature routers on first request (#26534)" (#26727)
This reverts commit 21ed38971d.
2026-04-29 00:21:41 +00:00
Michael-RZ-Berri
0520d5ce11
[Fix] Unify cost calc in success_handler dict and typed branches (#26629)
* Unify cost calc in success_handler dict and typed branches

* Trim verbose comments and docstrings

---------

Co-authored-by: Michael Riad Zaky <michaelr@Mac.localdomain>
Co-authored-by: Michael Riad Zaky <michaelr@Michaels-MacBook-Air.local>
2026-04-28 17:05:36 -07:00
Michael-RZ-Berri
21ed38971d
lazy-load optional feature routers on first request (#26534)
Co-authored-by: Michael Riad Zaky <michaelr@Mac.localdomain>
2026-04-28 17:04:40 -07:00
Michael Riad Zaky
6052ce1017 cache LiteLLM_Config param reads in DualCache + batch scheduler-tick fetch 2026-04-28 16:29:50 -07:00
Ryan Crabbe
b1a0a3fc17
fix(tests): use Sonnet 4.5 for Bedrock invoke prompt-caching tests
Claude 3.5 Sonnet v2 reached EOL on Bedrock 2026-03-01, returning the same
404 EOL error as 3.7 Sonnet. Sonnet 4.5 supports both InvokeModel and
Converse APIs on Bedrock, so use the same model for both routes.
2026-04-28 14:51:47 -07:00
Ryan Crabbe
dc46467235
fix(tests): replace deprecated Bedrock Claude 3.7 Sonnet model ID
AWS Bedrock has reached end-of-life for `claude-3-7-sonnet-20250219-v1:0`,
returning 404s with "This model version has reached the end of its life."
Update test references to `claude-sonnet-4-5-20250929-v1:0` (same capability
surface: thinking, tools, prompt caching, PDF input, vision, computer use).

The bedrock/invoke pass-through tests stay on Sonnet 3.5 since Sonnet 4.5
is converse-only on Bedrock.
2026-04-28 14:24:19 -07:00
harish-berri
18996326ef update test cases to fix handle_jwt test cases 2026-04-28 21:17:53 +00:00
harish-berri
84b6bd60af update test cases to match new behaviour. The earlier test cases assumed the cache stores a pydantic object 2026-04-28 21:08:46 +00:00
Josh Minzner
12e1d02d4e address Greptile review feedback on tool-result PDF fix
- Tighten _is_anthropic_document_data_uri to match the mimes Anthropic
  actually accepts as base64 `document` source ({application/pdf,
  text/plain}). The previous application/* + text/* prefix match would
  route e.g. data:application/json URIs through the document path,
  producing blocks the Anthropic API rejects. Unsupported mimes now
  stay on the existing image code path (same failure mode as before the
  fix — no regression, just stops introducing a new one).

- On the Bedrock tool-result `type: "file"` branch, accept either
  file_data or file_id and raise BadRequestError on both-None, mirroring
  the user-message _process_file_message pattern. Previously a file
  block with only file_id was silently dropped.

- Consolidate the six new PDF tool-result tests under tests/test_litellm/
  only (the PR template's required location and where the unit-test CI
  workflow runs with coverage). The duplicate copies under
  tests/llm_translation/ added drift risk with no additional coverage.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 16:48:29 -04:00
harish-berri
3c2c61e1e4 refactor(proxy): replace DualCache with UserApiKeyCache for user API key management
- Updated instances of DualCache to UserApiKeyCache across multiple files to enhance cache handling for user API keys.
- Adjusted cache retrieval and storage methods to ensure proper serialization and deserialization of cached objects.
- Introduced a new UserApiKeyCache class to streamline caching logic and improve type safety.
- Updated relevant tests to reflect changes in caching behavior and ensure compatibility with the new cache implementation.
2026-04-28 19:15:03 +00:00
Josh Minzner
5b5363cd54 test: mirror PDF tool-result tests under tests/test_litellm
Duplicate the three Bedrock and three Anthropic tool-result tests into
tests/test_litellm/ so they're picked up by `make test-unit` (and its
coverage report). The originals in tests/llm_translation/ stay — they
run under integration and remain the canonical translation-suite
regression cases.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 14:54:54 -04:00
KunalG67
90bcd232c3 fix(ovhcloud): remove dead transform_response override
The parent OpenAIGPTConfig already handles reasoning->reasoning_content
for non-streaming via _extract_reasoning_content. The override was dead
code giving false confidence. Streaming fix in chunk_parser is the only
change needed for chat completions.

Addresses Agent Shin review feedback on #26595
2026-04-28 23:09:17 +05:30
yuneng-jiang
600d7b4a20
Merge pull request #26675 from BerriAI/litellm_/zen-snyder-4c197e
fix(vertex): preserve items on array branches in anyOf with null + de-flake test
2026-04-28 10:31:34 -07:00
Sameer Kankute
898040fcdd
Fix tests 2026-04-28 22:34:14 +05:30
Josh Minzner
50eba8a3e2 fix(bedrock, anthropic): translate OpenAI file content on tool-result path
OpenAI Chat Completions `{type: "file", file: {file_data: "data:application/pdf;..."}}`
content blocks inside tool messages were silently dropped when translated to
Bedrock Converse and direct Anthropic. Additionally, PDFs sent via `image_url`
data URIs were either dropped (Bedrock) or wrapped as `type: "image"` and
rejected by the API (Anthropic).

- _convert_to_bedrock_tool_call_result: add `type: "file"` branch; pass through
  document blocks produced by BedrockImageProcessor for PDF `image_url` URIs.
  Single choke point covers both sync and async converse paths.
- convert_to_anthropic_tool_result: add `type: "file"` branch delegating to
  `anthropic_process_openai_file_message`; branch `image_url` on data-URI mime
  type so non-image mimes route through the file helper to produce document
  blocks.
- AnthropicMessagesToolResultParam.content union extended to accept
  `AnthropicMessagesDocumentParam` alongside text and image.
- Add 6 tests (3 Bedrock + 3 Anthropic) covering file-PDF, image_url-PDF, and
  image_url-PNG regression.

Fixes #24641
Supersedes #24646 with an OpenAI-native approach and test coverage.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 13:00:48 -04:00
Yuneng Jiang
1af11d4371 fix(vertex): synthesize items for array types missing items entirely
Companion to the prior commit. process_items only converted empty
`items: {}` to `{"type": "object"}`. But anyOf branches like
`{"type": "array"}` (no items field at all) were untouched, so after
convert_anyof_null_to_nullable stripped the null branch and added
nullable, the array branch was sent to Vertex as
`{"type": "array", "nullable": true}` — which Vertex rejects with
INVALID_ARGUMENT (`any_of[0].items: missing field`).

Make process_items synthesize `items: {"type": "object"}` for any
`type == "array"` schema where items is missing or empty.

Also:
- Convert test_gemini_tool_calling_working_demo to a hermetic mock
  test asserting items is present on the array branch in the sent
  body. Was previously a real-network call to Vertex and was the
  test the user reported still failing in CI.
- Add unit test test_build_vertex_schema_array_branch_missing_items_in_anyof
  covering the missing-items shape directly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 09:23:55 -07:00
Sameer Kankute
1d56e732e8
fix(vertex-ai): reuse anthropic messages config instances (#26099)
Cache provider config lookups for Vertex Anthropic messages so repeated requests reuse the same config object and preserve credential cache state. Add a regression test to catch any future loss of config reuse.

Made-with: Cursor
2026-04-28 08:44:40 -07:00
milan-berri
52fb23a512
fix(logging): backfill streaming hidden response cost (#26606)
* fix(logging): backfill streaming hidden response cost

Made-with: Cursor

* fix(logging): avoid mutating streaming hidden params

Backfill calculated streaming response cost into logging payload copies so OTEL spans expose hidden_params.response_cost without mutating the response object.

Made-with: Cursor

* fix black formatting

Apply the repo-pinned Black 24.10.0 formatting expected by CI.

Made-with: Cursor

* fix(types): allow numeric hidden response cost

Allow standard logging hidden params to carry numeric response_cost values, matching LiteLLM's calculated cost payloads.

Made-with: Cursor

* refactor(logging): simplify hidden response cost backfill

Clean up metadata initialization and reuse the raw response cost when deciding whether to backfill hidden params.

Made-with: Cursor
2026-04-28 08:41:20 -07:00
milan-berri
10aed9e981
feat(logging): add retry settings for generic API logger (#26645)
* Add retry settings for generic API logger

Made-with: Cursor

* Refine generic API retry behavior

Made-with: Cursor
2026-04-28 08:38:17 -07:00
michelligabriele
0dd64baa66
fix(caching): preserve prompt_tokens_details through embedding cache round-trip (#26653)
* fix(caching): preserve prompt_tokens_details through embedding cache round-trip

The embedding caching layer was dropping prompt_tokens_details (including
image_count) because CachedEmbedding had no field for usage metadata and
the cache retrieval code reconstructed Usage without it. This caused
inconsistent responses where the first call returned image_count but
cached responses did not, breaking cost tracking for multimodal embeddings.

Add prompt_tokens_details to CachedEmbedding, persist per-item details
during cache storage, aggregate them on retrieval, and merge them in
combine_usage() for partial cache hits.

* style: apply Black formatting to caching files

* fix(caching): address Greptile review — cyclic import, guarded construction, nested dict merge

Move PromptTokensDetailsWrapper to inline import to resolve CodeQL cyclic
import warning. Guard PromptTokensDetailsWrapper construction with
try/except to handle unexpected cached keys. Add recursive dict merging
in _merge_prompt_tokens_details for nested fields like
cache_creation_token_details.
2026-04-28 08:25:11 -07:00
Sameer Kankute
77d48e739d
chore(proxy): remove unintended generated and local files from prior commit
Drop accidental dashboard export path renames in _experimental/out, remove committed local proxy log, and remove the unintended ad-hoc test file so the feature commit only contains intentional source changes.

Made-with: Cursor
2026-04-28 18:57:55 +05:30
Sameer Kankute
c4e074f277
feat(proxy): add model-like search tool access control
Treat search tools like models by adding team/key allowed_search_tools controls, enforcing search tool authorization checks, and moving credential ownership to search tool config only to avoid exposing secrets in team metadata.

Made-with: Cursor
2026-04-28 18:53:32 +05:30