Commit graph

1737 commits

Author SHA1 Message Date
Sameer Kankute
b41627aa60 Fix greptile reviews and mock test 2026-03-23 22:49:57 +05:30
Sameer Kankute
0450194474 Fix greptile reviews and mock test 2026-03-23 22:26:08 +05:30
Sameer Kankute
27eff7a9f8 Fix greptile comments 2026-03-23 20:12:06 +05:30
Sameer Kankute
d3a8ebe930 Fix greptile comments 2026-03-23 18:26:43 +05:30
Sameer Kankute
a080352976 perf(routing): optimize team model checks and improve test coverage
- Use O(1) team index lookup instead of map_team_model in alias guard
- Fix MockPrismaClient to validate where clause filters
- Add comment explaining DB query trade-off for team deployments

Made-with: Cursor
2026-03-23 17:56:03 +05:30
Sameer Kankute
a1aa1176fa fix(routing): prevent stale model_aliases from interfering with team routing
- Skip model_aliases rewrite if model resolves to team deployments
- Add test coverage for sibling-preservation branch
- Update MockPrismaClient to support sibling deployment scenarios

Made-with: Cursor
2026-03-23 17:33:07 +05:30
Sameer Kankute
9465f0b642 fix(management): query DB directly for sibling deployments on rename
- Add clarifying comments to test assertions
- Query prisma DB instead of in-memory router to avoid stale state
- Prevents incorrect deletion of old public name when siblings exist

Made-with: Cursor
2026-03-23 17:10:11 +05:30
Sameer Kankute
53d3d6c146 fix(team-routing): keep team model routing on public names
Remove team model_alias rewrites and resolve team deployments by team_public_model_name with team_id so sibling deployments stay in the routing candidate pool, with explicit logs showing candidate selection before load balancing.

Made-with: Cursor
2026-03-23 16:12:27 +05:30
Sameer Kankute
b6555b99c1 fix(team-routing): use deterministic team model group names
Use a deterministic internal model_name for team-scoped deployments so sibling deployments with the same public model share a routing group. This makes team alias writes idempotent and preserves multi-deployment failover/load balancing behavior.

Made-with: Cursor
2026-03-23 15:31:43 +05:30
yuneng-jiang
9963b31e07 Revert "fix(proxy): restore per-entity breakdown in aggregated daily activity endpoint"
This reverts commit 9c3fab24ad.
2026-03-21 21:37:29 -07:00
yuneng-jiang
e3d4c29d37
Merge pull request #24323 from BerriAI/litellm_ryan_march_20
litellm ryan march 20
2026-03-21 15:57:28 -07:00
yuneng-jiang
72fba093c8 Merge remote-tracking branch 'origin/main' into litellm_dev_sameer_16_march_week 2026-03-21 15:11:29 -07:00
yuneng-jiang
2b889f1627
Merge pull request #23471 from michelligabriele/fix/aggregated-activity-entity-breakdown
fix(proxy): restore per-entity breakdown in aggregated daily activity endpoint
2026-03-21 14:59:41 -07:00
Krish Dholakia
f911d8d865
Merge pull request #23818 from BerriAI/litellm_oss_staging_03_17_2026
fix(fireworks): skip #transform=inline for base64 data URLs (#23729)
2026-03-21 14:54:39 -07:00
yuneng-jiang
262534a3a5
Merge branch 'main' into litellm_dev_sameer_16_march_week 2026-03-21 14:30:57 -07:00
Ishaan Jaff
2ea9e207bd
Litellm ishaan march 20 (#24303)
* feat(redis): add circuit breaker to RedisCache to fast-fail when Redis is down (#24181)

* feat(redis): add circuit breaker env var constants

* feat(redis): add RedisCircuitBreaker and apply guard decorator to all async ops

* fix(dual_cache): fall back to L1 instead of re-raising on Redis increment failures

* test(caching): add circuit breaker unit tests

* fix(redis): fast-fail concurrent HALF_OPEN probes — only one probe at a time

* fix(dual_cache): return None fallback when in_memory_cache is absent and Redis fails

* test(caching): add regression tests for HALF_OPEN concurrency and None fallback

* Fix blocking sync next in __anext__ (#24177)

* Fix blocking sync next

* Update tests/test_litellm/litellm_core_utils/test_streaming_handler.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix PEP 479 regression in __anext__ sync iterator exhaustion

asyncio.to_thread re-raises thread exceptions inside a coroutine, where
PEP 479 converts StopIteration to RuntimeError before any except clause
can catch it. Add _next_sync_or_exhausted() module-level helper that
catches StopIteration in the thread and returns a sentinel instead, then
raise StopAsyncIteration in the coroutine.

Also rewrites the non-blocking test to use asyncio.gather() instead of
asyncio.create_task() (which returned None on Python 3.9 / pytest-asyncio
in CI), and adds an exhaustion regression test that drains the wrapper
fully and asserts no RuntimeError leaks out.

---------

Co-authored-by: Emerson Gomes <emerson.gomes@thalesgroup.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* feat: add git-subdir source type to claude-code/plugins API (#24223)

Support a third plugin source type `git-subdir` alongside the existing
`github` and `url` types, as documented in the official Claude Code
plugin marketplaces spec.

New format: {"source": "git-subdir", "url": "...", "path": "subdir/path"}

- Validates url and path fields are present and non-empty
- Rejects absolute paths, '..' segments, backslashes, and percent-encoded
  traversal sequences (including double-encoded variants via regex check)
- Extracts path validation into _validate_git_subdir_path() helper
- Updates Pydantic field description to document all three source types
- Adds isValidUrl() check for url/git-subdir source types in the UI form
- Adds "Git Subdir" option to the UI form with a required Path field
- Adds unit tests covering success, update, missing/empty fields,
  path traversal variants, and unknown source type

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* [FEAT] add extract_header and extract_footer to Mistral OCR supported params (#24213)

* docs: add git-subdir source type to claude-code plugin marketplace docs (#24289)

* fix(ui): swap J/K keyboard navigation in log details drawer (#24279) (#24286)

J should navigate down (next) and K should navigate up (previous),
matching vim/standard conventions.

* fix: use async_set_cache in user_api_key_auth hot path (#24302)

* fix: use async_set_cache in auth hot path to avoid blocking event loop

* test: assert no blocking set_cache call in _user_api_key_auth_builder

* test: broaden blocking call check to all sync DualCache methods

* test: fix regression test to actually catch blocking cache calls

* fix: ruff lint unused variable + UI build MessageManager error

- litellm/caching/redis_cache.py: remove unused variable 'e' in circuit
  breaker exception handler (F841)
- add_plugin_form.tsx: use MessageManager.error() instead of undefined
  message.error() for git URL validation

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* docs: add REDIS_CIRCUIT_BREAKER env vars to config_settings reference

Add REDIS_CIRCUIT_BREAKER_FAILURE_THRESHOLD and
REDIS_CIRCUIT_BREAKER_RECOVERY_TIMEOUT to the environment variables
reference table so test_env_keys.py passes.

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

---------

Co-authored-by: Emerson Gomes <emerson.gomes@thalesgroup.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Vincenzo Barrea <manamana88@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Robert Kirscht <rkirscht242@gmail.com>
Co-authored-by: Imgyu Kim <kimimgo@gmail.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
2026-03-21 12:40:11 -07:00
Sameer Kankute
4f1e484a9b Merge branch 'main' into litellm_dev_sameer_16_march_week
Resolve conflicts in common_request_processing.py (keep main streaming,
post_call_success_hook try/finally, deferred logging; retain skip_pre_call_logic)
and utils.py (defer + internal-call skip + sync success callbacks for all calls).

Tighten _has_post_call_guardrails for event_hook=None; align deferred
guardrail test. Sync model_prices_and_context_window_backup.json.

Pyright: narrow ignores for passthrough StreamingResponse and post_call hook.
Made-with: Cursor
2026-03-22 00:29:38 +05:30
Krrish Dholakia
509d2e9ac3 Fix PR review issues: gpt-4-0314 prompt caching, case-insensitive data URL check, test I/O mocking
- Remove incorrect supports_prompt_caching from gpt-4-0314 (predates the feature)
- Make data-URL detection case-insensitive in Gemini tool call result conversion
- Mock show_banner/generate_feedback_box in max_budget tests to prevent real I/O

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 11:30:29 -07:00
Krish Dholakia
a5b7e49713
Merge branch 'main' into litellm_oss_staging_03_17_2026 2026-03-21 10:40:48 -07:00
Sameer Kankute
49abf98a27
Merge branch 'main' into litellm_oss_staging_03_17_2026 2026-03-21 21:16:49 +05:30
Sameer Kankute
a427807796
Merge branch 'main' into litellm_dev_sameer_16_march_week 2026-03-21 21:16:07 +05:30
Sameer Kankute
5b5c998dbd
Merge branch 'main' into litellm_oss_staging_03_19_2026 2026-03-21 20:31:08 +05:30
ryan-crabbe
1da02b66f6
Merge branch 'main' into litellm_audit_log_s3_export 2026-03-20 16:39:54 -07:00
ryan-crabbe
59b4a05782
Merge branch 'main' into litellm_ryan_march_18 2026-03-20 13:36:37 -07:00
yuneng-jiang
5927a77a14
Merge branch 'main' into fix/aggregated-activity-entity-breakdown 2026-03-20 11:50:59 -07:00
yuneng-jiang
f884e4ac66
Merge branch 'main' into fix/team-member-budget-duration-on-create 2026-03-20 11:48:08 -07:00
Sameer Kankute
7bf16b25d2
Merge pull request #24079 from Sameerlite/Sameerlite/passthrough-auth-fix
fix(proxy): pass-through subpath auth for non-admin users
2026-03-20 17:37:13 +05:30
Sameer Kankute
009cbfa799
Merge pull request #24088 from Point72/ephrimstanley/limits
feat: add proxy-wide default api key tpm/rpm limits
2026-03-20 14:46:38 +05:30
Ryan Crabbe
ad43a35d76 feat: add control plane for multi-proxy worker management
Adds a control plane capability that enables a central admin instance
to manage multiple regional worker proxies from a single UI.

Backend:
- Worker registry loaded from YAML config (worker_id, name, url)
- /.well-known/litellm-ui-config exposes is_control_plane and workers list
- /v3/login + /v3/login/exchange: opaque code exchange for cross-origin
  username/password auth (JWT never in URL/logs, single-use 60s TTL)
- SSO cookie handoff with return_to → opaque code → exchange
- _validate_return_to: full origin validation (scheme+hostname+port)
- Startup warning when control_plane_url set without Redis
- Both /v3 endpoints gated behind control_plane_url config

Frontend:
- Worker selector dropdown on login page (gated behind is_control_plane)
- Cross-origin SSO code exchange handling on callback
- switchToWorkerUrl: localStorage-persisted worker URL for API calls
- useWorker hook: shared worker state management
- WorkerDropdown in navbar for switching workers
- Logout/switch clears worker state from localStorage

Tests:
- 7 tests for /v3/login + /v3/login/exchange
- 10 tests for _validate_return_to
- 2 tests for control plane discovery endpoint
2026-03-19 22:50:19 -07:00
Sameer Kankute
784f9431ad
Merge pull request #24188 from BerriAI/main
merge main 0319
2026-03-20 11:03:54 +05:30
Sameer Kankute
c545c969f7
Merge branch 'main' into litellm_oss_staging_03_17_2026 2026-03-20 08:42:41 +05:30
Krish Dholakia
75386d4cb9
Merge pull request #24149 from michelligabriele/fix/kill-orphaned-prisma-engine-on-reconnect
fix(proxy): kill orphaned prisma engine subprocess on failed disconnect
2026-03-19 18:12:58 -07:00
yuneng-jiang
0781f68b8a
Merge pull request #24150 from BerriAI/litellm_yj_march_18_2026
[Infra] Merge daily internal branch with main
2026-03-19 16:43:47 -07:00
yuneng-jiang
05620c87e3 [Fix] Update bulk key update tests for find_unique refactor
Tests were outdated after _get_and_validate_existing_key was refactored
to use prisma_client.db.litellm_verificationtoken.find_unique() and
ProxyException. Also add ProxyException handling in bulk_update_keys
error extractor so error messages aren't empty.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 15:34:44 -07:00
yuneng-jiang
e86ca7f34d Revert "[Fix] Update tests for _get_and_validate_existing_key refactor"
This reverts commit cf63697703.
2026-03-19 14:32:14 -07:00
Krish Dholakia
739356640b
Merge pull request #24120 from BerriAI/litellm_proxy-azure-api-version-bump
feat(proxy): use AZURE_DEFAULT_API_VERSION for proxy --api_version default
2026-03-19 12:54:14 -07:00
yuneng-jiang
cf63697703 [Fix] Update tests for _get_and_validate_existing_key refactor
Tests were outdated after _get_and_validate_existing_key was refactored
to use prisma_client.db.litellm_verificationtoken.find_unique() instead
of prisma_client.get_data(), and to raise ProxyException instead of
HTTPException. Also fix bulk_update_keys error handler to extract
ProxyException.message (str(ProxyException) returns empty string).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 12:41:11 -07:00
michelligabriele
92b8e1acf8 address greptile review: async sleep, SIGKILL Windows guard, trailing newlines 2026-03-19 20:03:07 +01:00
yuneng-jiang
afb35204ce Merge remote-tracking branch 'origin' into litellm_yj_march_18_2026 2026-03-19 11:53:58 -07:00
michelligabriele
1f04fa2461 fix(proxy): kill orphaned prisma engine subprocess on failed disconnect 2026-03-19 19:50:39 +01:00
Ishaan Jaff
81dadb698a
Ishaan - March 18th changes (#24056)
* add DD Tracing (#24033)

* feat(models): add Azure GPT-5.4 mini and nano variants (#24045)

Add `azure/gpt-5.4-mini` and `azure/gpt-5.4-nano` to the model
database with official pricing from Azure OpenAI:

- GPT-5.4 mini: $0.75/M input, $0.075/M cached, $4.5/M output
- GPT-5.4 nano: $0.20/M input, $0.02/M cached, $1.25/M output

Both models support:
- 1.05M input / 128K output context window
- Chat, batch, and responses endpoints
- Function calling, tools, vision, reasoning
- Prompt caching with automatic tiered pricing

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* Add new model pricing details for volcengine Doubao-Seed-2.0 series (#23871)

Add entries for volcengine Doubao-Seed-2.0 series

* fix(mcp): support refresh_token grant type in OAuth token endpoint (#23701)

* fix(mcp): support refresh_token grant type in OAuth token endpoint (#23700)

The .well-known/oauth-authorization-server metadata advertises
refresh_token as a supported grant type, but the token endpoint
rejected it with HTTP 400. This adds refresh_token grant support
so MCP clients can refresh expired tokens without re-authenticating.

* test(mcp): add tests for refresh_token grant type in OAuth token endpoint

* fix(mcp): move code_verifier guard into authorization_code branch

code_verifier is only relevant for authorization_code grants (PKCE).
Move it inside the else branch so it doesn't apply to refresh_token.

* fix(mcp): guard None client_secret and forward scope in token exchange

- Conditionally include client_secret in form data to prevent httpx
  from sending the literal string "None" (applies to both
  authorization_code and refresh_token branches)
- Forward optional scope parameter per RFC 6749 §6, allowing clients
  to request a subset of originally-granted scopes on refresh

* fix(mcp): validate code param in authorization_code grant

Guard against None code being form-encoded as literal string "None"
by httpx, symmetric with the existing refresh_token guard.

* docs: add incident report for guardrail logging secret exposure (#24059)

Add blog post documenting the guardrail logging path exposing internal
request data (e.g. Authorization headers) in spend logs and OTEL traces.
Fix available in LiteLLM 1.82.3+.

Made-with: Cursor

* [Fix] Datadog LLM Observability tags format (env, service, version missing) (#23673)

* tag fix

* greptile comment

* fix(ci): stabilize 6 failing CI jobs

1. mypy: remove duplicate type annotation for token_data in discoverable_endpoints.py
2. integrations tests: add parameterized to CI test deps
3. doc quality: document OTEL_IGNORE_CONTEXT_PROPAGATION env key
4. security: allowlist CVE-2026-2673, CVE-2026-3644, CVE-2026-4224 (no fix available)
5. proxy_store_model_in_db: fix missing x-litellm-call-id header on error responses
6. google tests: add --retries 3 for transient Vertex AI rate limits

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* fix(streaming): handle RuntimeError during model_copy in streaming handler

The race condition occurs when model_copy(deep=True) tries to deepcopy
_hidden_params dict while it's being concurrently modified by logging
callbacks. Fall back to shallow copy if the deep copy fails.

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* fix(cost): handle non-string traffic_type in cost calculator + add retries

1. Fix AttributeError in _map_traffic_type_to_service_tier when traffic_type
   is an integer (cast to str before calling .upper()). This was causing
   pass-through vertex spend logging to fail silently.
2. Add --retries to llm_translation_testing for flaky external API calls.

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

---------

Co-authored-by: Emerson Gomes <emerson.gomes@thalesgroup.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: ExMatics HydrogenC <33123710+HydrogenC@users.noreply.github.com>
Co-authored-by: Jack Venberg <jack.venberg@rover.com>
Co-authored-by: milan-berri <milan@berri.ai>
Co-authored-by: Shivam Rawat <161387515+shivamrawat1@users.noreply.github.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
2026-03-19 10:20:35 -07:00
michelligabriele
0057452485 fix(proxy): guard streaming deferred init with try/finally, fix test imports
Wrap _run_deferred_stream_guardrails initialization (UnifiedLLMGuardrails
constructor and _check_and_merge_model_level_guardrails) in try/finally
so logging always fires even if init throws. Prevents silent logging loss
on transient errors.

Move fastapi.HTTPException import from module-level to local test-function
scope. Add test_logging_fires_even_if_guardrail_init_raises to verify the
try/finally guard.
2026-03-19 18:00:49 +01:00
michelligabriele
4b8c532ba8 fix(proxy): pass guardrail_data to hooks in streaming deferred path
Use the merged guardrail_data dict (from _check_and_merge_model_level_guardrails)
for hook invocations in _run_deferred_stream_guardrails, instead of the original
captured_data. This ensures model-level non-default guardrails are visible to
inner should_run_guardrail re-checks inside UnifiedLLMGuardrails.

Rewrite three hand-crafted closure tests to exercise the production
_run_deferred_stream_guardrails exception-handling path. Add three new tests
that use deep-copy mocks to prove hooks receive the merged dict.
2026-03-19 17:39:06 +01:00
michelligabriele
001501fb31 fix(proxy): defer logging until post-call guardrails complete
guardrail_information is None in StandardLoggingPayload because logging
fires before post-call guardrails write to metadata.

Non-streaming: wrapper_async stores a closure instead of calling
create_task immediately. The proxy fires it in a try/finally after
post_call_success_hook so the SLP is built with guardrail info.

Streaming: a closure on logging_obj is called by CSW.__anext__ at
stream end. The closure runs only guardrail hooks (not all callbacks)
on the assembled response, then fires both logging handlers. This
avoids behavioral changes for non-guardrail callbacks on streaming.
2026-03-19 16:49:30 +01:00
Ephrim Stanley
ae0769b1df fix: guard empty-dict team limits and malformed int in deployment default limits
- Change `if team_limit:` to `if team_limit is not None:` in both
  get_key_model_rpm_limit and get_key_model_tpm_limit so that an
  explicitly-empty team rate-limit map ({}) is returned as-is instead
  of silently falling through to deployment defaults (P1 fix).
- Replace the bare `int()` list comprehension in _get_deployment_default_limit
  with a loop that catches ValueError/TypeError so malformed config strings
  do not raise an unhandled exception during request handling (P2 fix).
- Add corresponding unit tests for both edge cases.

Co-Authored-By: Claude (claude-sonnet-4-6) <noreply@anthropic.com>
2026-03-19 07:40:47 -04:00
Ephrim Stanley
e562c1d064 refactor: consolidate duplicate helpers and eliminate success-handler double lookup
- Merge _get_deployment_default_rpm_limit and _get_deployment_default_tpm_limit
  into a single _get_deployment_default_limit(model_name, field) helper; the two
  thin wrappers are preserved for callers but share one implementation
- Compute _success_tpm_limit / _success_rpm_limit once before the guard condition
  in async_log_success_event, eliminating the previous two unconditional
  get_key_model_* calls (each of which could hit llm_router.get_model_list)
- Replace fragile llm_model_list=[{}] sentinel in test with []

Co-Authored-By: Claude (claude-sonnet-4-6) <noreply@anthropic.com>
2026-03-19 07:26:43 -04:00
Sameer Kankute
532e0d13df feat(proxy): use AZURE_DEFAULT_API_VERSION for proxy --api_version default
Aligns proxy default with litellm.AZURE_DEFAULT_API_VERSION (2025-02-01-preview)
so Azure response_format + json_schema works without tools fallback.

Made-with: Cursor
2026-03-19 15:57:03 +05:30
Sameer Kankute
e2e4f9ed33
Merge branch 'main' into litellm_oss_staging_03_17_2026 2026-03-19 15:53:06 +05:30
Ephrim Stanley
477c54184b perf: avoid unconditional router lookups in success handler
Replace bare _get_deployment_default_tpm/rpm_limit calls in the
async_log_success_event condition with get_key_model_tpm/rpm_limit
(model_name=model_group). The higher-level getters short-circuit on
key/team metadata hits before ever reaching the router, so requests
that don't use deployment defaults incur no extra router lookup. Remove
the now-unused bare helper imports.

Also fix invalid `int = None` type hints in test helper signatures
to `Optional[int] = None`.

Co-Authored-By: Claude (claude-sonnet-4-6) <noreply@anthropic.com>
2026-03-19 02:07:50 -04:00
Ephrim Stanley
36dc893770 fix: address review feedback on default tpm/rpm limits
- Use min() across all matching deployments instead of first-wins when
  resolving default_api_key_tpm/rpm_limit for a model group, so
  load-balanced setups with different per-deployment limits always apply
  the most conservative value
- Replace the global SensitiveDataMasker non_sensitive_overrides change
  with a targeted excluded_keys set at the remove_sensitive_info_from_deployment
  call site, avoiding unintended suppression of other fields
- Update the v1 parallel request limiter to pass model_name to
  get_key_model_tpm/rpm_limit so deployment defaults apply there too
- Add 4 tests covering multi-deployment min semantics

Co-Authored-By: Claude (claude-sonnet-4-6) <noreply@anthropic.com>
2026-03-19 01:43:27 -04:00