Commit graph

37495 commits

Author SHA1 Message Date
Utsab Dahal
e3d160f158
fix(embedding): omit null encoding_format for openai requests (#25395) 2026-04-11 19:39:19 -07:00
Darien Kindlund
17e145a083
fix(proxy): use model_group for model_max_budget spend tracking cache key (#25549)
The model_max_budget limiter tracks spend in one code path
(async_log_success_event) and enforces budget limits in another
(is_key_within_model_budget via user_api_key_auth). These two paths
used different model name formats to build cache keys:

- Tracking used standard_logging_payload["model"], which is the
  deployment-level model name (e.g. "vertex_ai/claude-opus-4-6@default")
- Enforcement used request_data["model"], which is the model group
  alias (e.g. "claude-opus-4-6")

Because the cache keys never matched, the enforcement path always read
None for current spend, silently allowing all requests through even
after the budget was exceeded. This affected any provider that decorates
model names with provider prefixes or version suffixes (Vertex AI,
Bedrock, etc.).

Fix: use model_group (the user-facing alias) from StandardLoggingPayload
for spend tracking, falling back to model when model_group is None.
This aligns the tracking cache key with the enforcement cache key.

Fixes the same root cause reported in #15223 and #10052.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 19:37:58 -07:00
Darien Kindlund
f54e4e664b
fix(proxy): use _hash_token_if_needed for cache invalidation in bulk update and key rotation (#25552)
Two code paths in key_management_endpoints.py call hash_token()
unconditionally when invalidating the user_api_key_cache after a key
update.  When the caller passes a pre-hashed token ID (not an sk-
prefixed key), hash_token() double-hashes it, producing a cache key
that does not match the actual cached entry.  Cache invalidation
silently fails.

This is compounded by update_cache() which writes the stale cached key
object back with a fresh 60s TTL after every successful request,
preventing natural TTL expiry.  The stale entry (with outdated fields
like max_budget=None) persists indefinitely under load.

PR #24969 fixed this in update_key_fn but missed two other call sites:
- _process_single_key_update (bulk update path)
- _execute_virtual_key_regeneration (key rotation path)

Fix: replace hash_token() with _hash_token_if_needed() in both
locations, matching the pattern already used elsewhere in the file.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 19:36:40 -07:00
ishaan-berri
fdd7500904
blog: add back arrow to blog post pages (#25587)
* blog: add back arrow to post pages

* blog: style back arrow — fixed top-left below navbar
2026-04-11 19:15:45 -07:00
ishaan-berri
1edf41c26f
Merge pull request #25585 from BerriAI/litellm_dev_04_11_2026_p1
Litellm dev 04 11 2026 p1
2026-04-11 18:46:57 -07:00
Krrish Dholakia
973986aac2 docs: readme tweak 2026-04-11 18:34:23 -07:00
ishaan-berri
329a526b9d
Merge pull request #25579 from BerriAI/feat/anthropic-advisor-tool
feat(advisor): advisor tool orchestration loop for non-Anthropic providers
2026-04-11 18:32:44 -07:00
ishaan-berri
12c1467228
Merge pull request #25583 from BerriAI/blog/ramp-style-restyle-with-redis-post
blog: Ramp-style engineering blog restyle + Redis circuit breaker post
2026-04-11 18:31:34 -07:00
Ishaan Jaffer
dd87f3be5b
docs(advisor): move supported providers to top, focus how it works on litellm native loop 2026-04-11 18:27:18 -07:00
Ishaan Jaffer
a8bc7bfcd4
docs(advisor): add how it works section with mermaid diagram + non-native provider table 2026-04-11 18:23:33 -07:00
Ishaan Jaffer
9be7b4c07c
test(advisor): add integration tests for full dispatch path, max_uses, provider bypass 2026-04-11 18:16:56 -07:00
Ishaan Jaffer
fa5258466d
test(advisor): add unit tests for max_uses=0, missing model, default fallback 2026-04-11 18:16:56 -07:00
Ishaan Jaffer
22f45c6666
fix(advisor): restore AdvisorMaxIterationsError, raise on cap, fix max_uses=0 falsy 2026-04-11 18:16:56 -07:00
Ishaan Jaffer
35f4b47ff8
apply content guidelines: scale/resilience narrative, FAQ, Key Takeaways, Conclusion CTA 2026-04-11 18:12:32 -07:00
ishaan-berri
f74d626253
Merge pull request #25580 from BerriAI/blog/ramp-style-restyle-with-redis-post
blog: restyle docs.litellm.ai/blog to engineering blog aesthetic
2026-04-11 18:10:57 -07:00
Ishaan Jaffer
d29f40d39f
fix(advisor): inject max_uses_exceeded error result instead of raising exception
When the advisor loop hits max_uses, inject a tool_result error so the executor
sees the cap and continues without further advice — matches Anthropic server-side
behaviour (error_code: max_uses_exceeded).
2026-04-11 18:03:12 -07:00
Ishaan Jaffer
14eed24471
add redis circuit breaker blog post with React diagrams 2026-04-11 18:02:59 -07:00
Ishaan Jaffer
8e616ecdf4
add BlogPostPage swizzle: hide sidebar, add hiring CTA on every post 2026-04-11 18:02:56 -07:00
Ishaan Jaffer
dac44fb443
blog list styles: clean typography, marquee animation, hero layout 2026-04-11 18:02:52 -07:00
Ishaan Jaffer
85cb7db8b9
blog list page: Ramp-style flat list with hero, provider marquee, hiring CTA 2026-04-11 18:02:48 -07:00
Ishaan Jaffer
05d516482f
restyle blog list page to match engineering blog aesthetic 2026-04-11 18:02:44 -07:00
Yuneng Jiang
7c6bd98fdf
fix: address PR review comments on RegenerateKeyModal
- Remove redundant useEffect cleanup that duplicated handleClose logic
- Remove unnecessary currentAccessToken state, use accessToken from hook directly
2026-04-11 18:01:02 -07:00
Ishaan Jaffer
844e34b68b
test(advisor): remove live e2e test file (tests run locally via script) 2026-04-11 17:52:06 -07:00
Ryan Crabbe
30c2357fe3
fix(ui/team): annotate effectiveGuardrails as string[] for strict typecheck
Some checks failed
Unit Tests: Proxy DB Operations / proxy-db (auth-checks, tests/proxy_unit_tests/test_auth_checks.py tests/proxy_unit_tests/test_user_api_key_auth.py, 20, 8) (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-db (key-generation, tests/proxy_unit_tests/test_key_generate_prisma.py, 30, 0) (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-db (remaining, tests/proxy_unit_tests --ignore=tests/proxy_unit_tests/test_key_generate_prisma.py --ignore=tests/proxy_unit_tests/test_auth_checks.py --ignore=tests/proxy_unit_tests/test_user_api_key_auth.py, 20, 8) (push) Has been cancelled
Unit Tests: Security / security (push) Has been cancelled
The new effectiveGuardrails computation derived its element type from
`info.metadata?.guardrails`, which is implicitly typed `any[]`, so the
downstream `.map((name) => ...)` callback inferred `name` as implicit
`any` and broke the production typecheck.
2026-04-11 17:48:16 -07:00
Ryan Crabbe
3d72e2a6f3
fix(guardrails): address PR #25575 review feedback + sync kill switch with opt-out list
Renames the new per-guardrail opt-out field from `disabled_global_guardrails`
to `opted_out_global_guardrails` to eliminate the one-character collision with
the legacy `disable_global_guardrails` boolean kill switch. Adds a type guard
on the new gate so a misnamed bool can't crash the guardrail check. Filters
duplicates out of the team-edit guardrail display for legacy teams that have a
global name persisted in `metadata.guardrails` from before this PR. Drops the
unused `isGuardrailsLoading` and `guardrailsError` destructures left in
AddModelForm after the hook refactor.

Adds Python tests for the new gate behavior (root, litellm_metadata, metadata,
non-matching name, empty list, malformed bool value, opt-in coexistence) and
extends useGuardrails.test.ts to exercise the global / optional partition
logic that the rebuilt hook performs in its `select` transform.

Wires the legacy kill switch and the new opt-out list together in the team
edit form so they can never fall out of sync:

- Toggling the kill switch reactively updates the Guardrails Select via
  `onValuesChange` — switch on strips all globals from the selection, switch
  off re-adds them. Existing opt-in extras are preserved either way.
- When the switch is on, global options in the Select are individually
  disabled (greyed out) so the user can still manage opt-in guardrails but
  cannot accidentally re-enable a global the kill switch is bypassing.
- The save handler writes both fields together: `disable_global_guardrails`
  reflects the switch, and `opted_out_global_guardrails` is set to either
  every global (when the switch is on) or the user's explicit opt-outs.
- `effectiveGuardrails` for the form's initialValues honors the kill switch
  on legacy teams so the form opens in a state that matches what the runtime
  gate is actually doing — fixes the visual lie where chips appeared active
  while the switch was bypassing them.

The backend gate already reads the list as the primary path with the bool
as a fallback, so untouched legacy teams keep working until they get edited,
at which point they migrate naturally.
2026-04-11 17:48:16 -07:00
Ryan Crabbe
59f66af0f9
fix(ui/team): wait for useGuardrails to resolve before rendering edit form
The team edit form computed its `guardrails` initialValues from
`globalGuardrailNames`, which is empty until `useGuardrails` resolves.
Because Ant Design's `<Form initialValues>` is read once on mount, a
user who clicked Edit before the query resolved would see globals
missing from the Select and could save that stale state, silently
opting the team out of every global guardrail.

Gate the form on `!isGuardrailsLoading` so initialValues always sees
the resolved set.
2026-04-11 17:48:16 -07:00
Ryan Crabbe
f9639654fa
feat(ui/team): per-guardrail opt-out for global guardrails
Replace the team info page's tags-mode guardrails Select with a grouped
multi-select that splits guardrails into "Global" (default_on=true) and
"Other" sections. On submit, derive both metadata fields from the single
selection array:

  - metadata.guardrails: non-global opt-ins (additive)
  - metadata.disabled_global_guardrails: globals the team has opted out of

The legacy disable_global_guardrails kill-switch toggle stays alongside
the multiselect and remains semantically distinct: it kills all global
guardrails including any added in the future, while the new list lets
new globals auto-apply unless explicitly excluded.

Other changes:
  - Switch from a manual useEffect/useState guardrails fetch to the
    consolidated useGuardrails hook
  - Replace stale "Select existing guardrails or enter new ones" help
    text with a single tooltip on each section's info icon
  - Render selected chips with green/blue color coding via tagRender so
    global vs non-global is visible without opening the dropdown
  - Drop the redundant [Global] tag from inside the OptGroup options
    (the group label already conveys it)
  - Update the read-only display to show the effective set (globals not
    opted out + additive opt-ins) with [Global] suffix on globals
2026-04-11 17:48:16 -07:00
Ryan Crabbe
a9d64f8620
refactor(ui/guardrails): expose full data from useGuardrails hook
Extend useGuardrails to return the full guardrail objects plus derived
globalGuardrailNames / optionalGuardrailNames sets via React Query's
select option, instead of just an array of names. Update its existing
consumer (AddModelForm) to extract names from the new shape.

The previous shape was tailored to AddModelForm's single use case
(populate a Select with names). The team info per-guardrail opt-out
work needs default_on per guardrail to split globals from non-globals,
which the old shape couldn't provide. Consolidating into the existing
hook gives both consumers one source of truth and one React Query
cache entry instead of two parallel fetches.

- useGuardrails.ts: rewrite return type, derive global/optional sets
  in select(); preserve the existing query key and auth-gate semantics
- AddModelForm.tsx: extract names from data?.guardrails.map(...)
- AddModelForm.test.tsx: update mock to return the new shape (also
  fixes a pre-existing shape mismatch in the mock)
- useGuardrails.test.ts: update 3 assertions to read names via
  data?.guardrails.map(...) instead of asserting against the flat array
2026-04-11 17:48:16 -07:00
Ryan Crabbe
88beed905e
feat(guardrails): per-team opt-out for specific global guardrails
Add disabled_global_guardrails list field to team metadata that
selectively skips named globals at request time. Coexists with the
existing disable_global_guardrails boolean kill switch — the boolean
kills all globals (including future ones), the new list selectively
skips named ones (new globals auto-apply).

The field lives in the team metadata JSON column; no schema migration.

- litellm/proxy/litellm_pre_call_utils.py: propagate the field from
  team_metadata into per-request data.metadata
- litellm/integrations/custom_guardrail.py: new
  get_disabled_global_guardrails_from_metadata helper plus a
  scoped-to-globals early return at the top of should_run_guardrail
2026-04-11 17:48:16 -07:00
Ishaan Jaffer
742e2fe1aa
test(advisor): add live e2e tests for advisor orchestration against real proxy 2026-04-11 17:46:17 -07:00
Ishaan Jaffer
ce3d039bcd
test(advisor): add unit tests for orchestration loop (mocked backends, 8 tests) 2026-04-11 17:43:26 -07:00
Ishaan Jaffer
b92e4c5595
docs(advisor): add interceptors README explaining when to use vs pre-request hooks 2026-04-11 17:43:23 -07:00
Ishaan Jaffer
c12ebdb221
feat(advisor): add AdvisorOrchestrationHandler for non-Anthropic providers 2026-04-11 17:43:20 -07:00
Ishaan Jaffer
ea765f7509
feat(advisor): add MessagesInterceptor ABC and registry 2026-04-11 17:43:16 -07:00
Ishaan Jaffer
ebc57a157d
feat(advisor): wire MessagesInterceptor registry into anthropic_messages handler 2026-04-11 17:43:13 -07:00
Ishaan Jaffer
a89b0672c7
feat(advisor): add replace_with_text param to strip_advisor_blocks_from_messages 2026-04-11 17:43:10 -07:00
Ishaan Jaffer
23e20facb6
feat(advisor): add ADVISOR_MAX_USES, ADVISOR_NATIVE_PROVIDERS, ADVISOR_TOOL_DESCRIPTION constants 2026-04-11 17:43:07 -07:00
Ryan Crabbe
ef38c665ca
fix(guardrails): use plural key in get_disable_global_guardrail
Rename disable_global_guardrail → disable_global_guardrails to match
the key name used by litellm_pre_call_utils.py, the API endpoints,
and the UI when propagating key/team metadata.

The singular form was introduced in PR #16983 and has never matched
the plural form written by the rest of the codebase, so the feature
silently did nothing.

Re-applies fix originally from #25488. Original commit could not be
merged due to missing signature.

Co-Authored-By: Remi Mabon <remi.mabon@redcare-pharmacy.com>
2026-04-11 17:35:50 -07:00
Krrish Dholakia
e08e3bf748 docs: clarify how to get benchmarking script 2026-04-11 17:31:03 -07:00
Krrish Dholakia
12bca649fc docs: refactor benchmarking docs to be clearer 2026-04-11 17:30:09 -07:00
yuneng-jiang
2c786ca2e6
Merge pull request #25578 from BerriAI/yj_apr11_bump
Some checks are pending
CodeQL / Analyze (actions) (push) Waiting to run
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
CodSpeed Benchmarks / benchmarks (push) Waiting to run
Helm unit test / unit-test (push) Waiting to run
Read Version from pyproject.toml / read-version (push) Waiting to run
Scorecard supply-chain security / Scorecard analysis (push) Waiting to run
Unit Tests: Proxy DB Operations / proxy-db (auth-checks, tests/proxy_unit_tests/test_auth_checks.py tests/proxy_unit_tests/test_user_api_key_auth.py, 20, 8) (push) Waiting to run
Unit Tests: Proxy DB Operations / proxy-db (key-generation, tests/proxy_unit_tests/test_key_generate_prisma.py, 30, 0) (push) Waiting to run
Unit Tests: Proxy DB Operations / proxy-db (remaining, tests/proxy_unit_tests --ignore=tests/proxy_unit_tests/test_key_generate_prisma.py --ignore=tests/proxy_unit_tests/test_auth_checks.py --ignore=tests/proxy_unit_tests/test_user_api_key_auth.py, 20, 8) (push) Waiting to run
Unit Tests: Security / security (push) Waiting to run
GitHub Actions Security Analysis / zizmor (push) Waiting to run
bump: version 1.83.6 → 1.83.7
2026-04-11 17:09:31 -07:00
Yuneng Jiang
e162c6d502
bump: version 1.83.6 → 1.83.7 2026-04-11 17:00:33 -07:00
yuneng-jiang
d7823e3a09
Merge pull request #25577 from BerriAI/yj_apr11_build_3
[Infra] Rebuild UI
2026-04-11 16:04:12 -07:00
Yuneng Jiang
a89ad3aaff
chore: update Next.js build artifacts (2026-04-11 22:57 UTC, node v22.16.0) 2026-04-11 15:57:01 -07:00
yuneng-jiang
99cb3af1a6
Merge pull request #25562 from BerriAI/litellm_internal_staging_04_11_2026
Litellm internal staging 04 11 2026
2026-04-11 15:55:29 -07:00
Yuneng Jiang
c40e459447
fix linting 2026-04-11 15:44:15 -07:00
Yuneng Jiang
909247785e
Merge remote-tracking branch 'origin' into litellm_internal_staging_04_11_2026 2026-04-11 15:41:03 -07:00
yuneng-jiang
9a43e32d6e
Merge pull request #25464 from BerriAI/litellm_passthrough_contenttype
fix(proxy): pass-through multipart uploads and Bedrock JSON body
2026-04-11 15:40:16 -07:00
shivam
3742b0cee1
refactor: define pass-through custom body state key in types module
Avoid module-level cyclic import between llm_passthrough_endpoints and
pass_through_endpoints; CodeQL and partial init order no longer risk
undefined LITELLM_PASS_THROUGH_CUSTOM_BODY_STATE_KEY.

Made-with: Cursor
2026-04-11 15:26:44 -07:00
shivam
574eb207c8
fix: import LITELLM_PASS_THROUGH_CUSTOM_BODY_STATE_KEY for bedrock passthrough
Fixes NameError when bedrock_proxy_route sets custom body on request.state.
Remove unused lazy-loader helper.

Made-with: Cursor
2026-04-11 15:08:10 -07:00