Commit graph

37589 commits

Author SHA1 Message Date
Sameer Kankute
e7bc1616cc
Merge pull request #26260 from BerriAI/litellm_internal_staging
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 (proxy-utils, tests/proxy_unit_tests/test_proxy_utils.py, 20, 8) (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 --ignore=tests/proxy_unit_tests/test_p… (push) Has been cancelled
Unit Tests: Security / security (push) Has been cancelled
merge main
2026-04-22 22:17:14 +05:30
yuneng-jiang
24aec61e4b
Merge pull request #26049 from BerriAI/litellm_adaptive_routing
Litellm adaptive routing
2026-04-22 08:52:51 -07:00
Sameer Kankute
47614f967b
refactor code 2026-04-22 17:47:27 +05:30
ishaan-berri
0e42d4cb08
April 21st Ishaan Branch (#26213)
* fix(otel): preserve Splunk Observability Cloud trace OTLP endpoint (#26183)

* fix(otel): preserve Splunk Observability Cloud trace OTLP URL

Splunk ingest uses /v2/trace/otlp; _normalize_otel_endpoint must not append /v1/traces.

- Return trace endpoints unchanged when they match Splunk OTLP path patterns
- Add unit tests for observability.splunkcloud.com, signalfx.com, and /trace/otlp suffix
- Set OTEL_EXPORTER_OTLP_PROTOCOL in protocol selection tests (from_env precedence over OTEL_EXPORTER)

Made-with: Cursor

* test(otel): use parameterized.expand for Splunk OTLP URL cases

Made-with: Cursor

* fix(otel): narrow Splunk trace URL guard to /v2/trace/otlp only

Made-with: Cursor

* test(otel): cover OTEL_EXPORTER fallback when OTLP protocol env unset

Made-with: Cursor

* Add Openrouter Opus 4.7 Entry (#26130)

---------

Co-authored-by: milan-berri <milan@berri.ai>
Co-authored-by: Matt Greathouse <matt5316@gmail.com>
2026-04-21 20:18:56 -07:00
ishaan-berri
e6897f5510
add moonshot/kimi-k2.6 to model registry (#26203)
* add moonshot/kimi-k2.6 to model registry

* add moonshot/kimi-k2.6 to backup model registry

* add tests for moonshot/kimi-k2.6 model registry

* fix moonshot/kimi-k2.6 pricing and add reasoning support

* fix moonshot/kimi-k2.6 pricing and add reasoning support in backup

* update kimi-k2.6 tests: fix pricing, add tool_choice and reasoning checks

* fix: load kimi-k2.6 registry tests from local backup instead of remote cost map
2026-04-21 19:58:43 -07:00
yuneng-jiang
eebb80fbef
Merge pull request #26208 from BerriAI/litellm_individual-team-member-budgets
Some checks are pending
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 (proxy-utils, tests/proxy_unit_tests/test_proxy_utils.py, 20, 8) (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 --ignore=tests/proxy_unit_tests/test_p… (push) Waiting to run
Unit Tests: Security / security (push) Waiting to run
Litellm individual team member budgets
2026-04-21 18:38:00 -07:00
yuneng-jiang
e3ed136f52
Merge pull request #26209 from BerriAI/yj_bump_apr21_2
[Infra] Bump version
2026-04-21 18:29:41 -07:00
Yuneng Jiang
e65d547c4d
adding uv lock 2026-04-21 18:10:47 -07:00
Yuneng Jiang
5837d4a9ac
bump: version 1.83.10 → 1.83.11 2026-04-21 18:10:31 -07:00
Krrish Dholakia
e50f945ef7 refactor(adaptive_router): move update_queue out of litellm.proxy
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 (proxy-utils, tests/proxy_unit_tests/test_proxy_utils.py, 20, 8) (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 --ignore=tests/proxy_unit_tests/test_p… (push) Has been cancelled
Unit Tests: Security / security (push) Has been cancelled
P1 review: adaptive_router.py had a top-level import of
AdaptiveRouterUpdateQueue from litellm.proxy.db, which broke the
SDK/proxy boundary that every other router strategy respects. No
other router_strategy module imports from litellm.proxy at module
level.

The queue only depends on litellm._logging — it never needed to
live under litellm.proxy. Moved:

  litellm/proxy/db/db_transaction_queue/adaptive_router_update_queue.py
  → litellm/router_strategy/adaptive_router/update_queue.py

  tests/test_litellm/proxy/db/db_transaction_queue/
    test_adaptive_router_update_queue.py
  → tests/test_litellm/router_strategy/adaptive_router/test_update_queue.py

Also switched the queue's logger from verbose_proxy_logger to
verbose_router_logger to match the new module's ownership.

P2 review: drop unused constant STAGNATION_JACCARD_EXACT from
config.py — it was defined but never referenced.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 18:02:44 -07:00
shivam
5770af0068
Merge branch 'litellm_internal_staging' into litellm_individual-team-member-budgets 2026-04-21 17:59:29 -07:00
shivam
27a105bcf9
fix: give each team member an independent budget instead of sharing the team default
Previously, members added to a team without an explicit per-member budget were
all linked to the same `litellm_budgettable` row referenced by the team's
`metadata.team_member_budget_id`. Updating one member's budget via
`/team/member_update` mutated the shared row and silently changed every other
member's budget too.

Now both write paths produce a private, per-member budget:

- `add_new_member` clones the team's default budget into a fresh row when a
  member is added without `max_budget_in_team`/`allowed_models`. If no team
  default exists, the membership is created with no budget.
- `_upsert_budget_and_membership` detects when an existing membership still
  points at the team's default budget id and clones-on-write, relinking the
  membership to the new private budget before applying the update.
- `team_member_update` reads `team_member_budget_id` from team metadata and
  passes it through so the helper can make this distinction.

Adds unit tests for clone-on-write, in-place update of a private budget, and
the no-default-no-budget add path.

Made-with: Cursor
2026-04-21 17:58:50 -07:00
Krrish Dholakia
1965c67e8f style: black format signals.py 2026-04-21 17:56:49 -07:00
Krrish Dholakia
37fc6f623b fix(adaptive_router/signals): rename 'args' to 'call_args' in _signature
The prevent_key_leaks_in_exceptions CI check forbids '{args}' in
f-strings because it's a common shape for accidental API key leaks
in exception messages. _signature() uses an entirely local variable
named 'args' for tool-call arguments (loop-detection signatures, no
exception path), but the grep is substring-based. Rename to 'call_args'.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 17:54:31 -07:00
yuneng-jiang
d9494b6990
Merge pull request #26144 from BerriAI/litellm_post_call_non_streaming
fix(bedrock_guardrails): use Bedrock OUTPUT source for apply_guardrail when scanning model responses
2026-04-21 17:50:16 -07:00
Krrish Dholakia
f1da202d9e fix(adaptive_router): P1 flusher hot-reload + P2 hook accumulation + CI
P1: start the adaptive-router flusher loop unconditionally at proxy boot
instead of gating on 'adaptive_routers is non-empty'. Adaptive routers
added via /config/reload after boot now have their queues drained.
State is lazy-loaded per router on first flush tick (new _state_loaded
flag on AdaptiveRouter) so hot-reloaded routers still get their
persisted priors.

P2: _finalize_adaptive_router_if_configured now prunes stale
AdaptiveRouterPostCallHook callbacks from every litellm callback list
before registering new ones. Without this, every Router replacement
left the old hooks wired up in litellm.callbacks and double-fired
signal recording for every request. Uses
logging_callback_manager.remove_callbacks_by_type (same pattern as the
semantic tool filter).

CI fixes:
- black --check failure: reformatted litellm/router.py
- schema migration diff: aligned @@index with the explicit index name
  ('idx_adaptive_router_session_activity') from the original migration
  by adding 'map:' to all three schema.prisma copies. No new migration
  needed.

Tests: 1 new covering the prune-on-hot-reload path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 17:49:38 -07:00
yuneng-jiang
5dc2926a1e
Merge pull request #26194 from BerriAI/litellm_fix_migration_thrashing
[Feature] Proxy: opt-in v2 migration resolver
2026-04-21 16:55:54 -07:00
yuneng-jiang
93cb0657d7
Merge pull request #26197 from BerriAI/litellm_yj_apr20
[Infra] Merge dev branch
2026-04-21 16:55:00 -07:00
Krrish Dholakia
ecd9a83e61 fix(adaptive_router): P2 review items — @updatedAt + snapshot samples
- Mark last_updated_at (AdaptiveRouterState) and last_activity_at
  (AdaptiveRouterSession) with @updatedAt so Prisma refreshes the
  timestamps on every write. Without this the fields stayed frozen at
  INSERT time and the last_activity_at index was misleading for any
  future TTL/eviction logic. Applied to all three schema.prisma copies;
  no migration SQL change needed (Prisma @updatedAt is a client-side
  annotation that doesn't touch DDL).

- get_state_snapshot: report cell.total_samples instead of alpha+beta
  for the 'samples' field. The previous value inflated every cell by
  the COLD_START_MASS prior (e.g. showed 10.0 before any real traffic
  arrived), which confused operators reading /adaptive_router/.../state.
  Updated docs + the snapshot test to match.

Also fixes two pre-existing merge-break syntax errors in router.py
(missing ')' on the AdaptiveRouter TYPE_CHECKING import; truncated
async_pre_routing_hook dispatch call for the adaptive router branch)
that were masking the rest of the file from the interpreter.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 16:27:01 -07:00
Krrish Dholakia
c7342bdc4f
Merge branch 'litellm_internal_staging' into litellm_adaptive_routing 2026-04-21 16:22:38 -07:00
Yuneng Jiang
8d52b1edd1
Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_yj_apr20 2026-04-21 16:21:10 -07:00
Yuneng Jiang
2b8b9502d9
[Fix] v2 resolver: swallow non-connection DB errors; wrap resolve failures
Addresses two further Greptile findings:

- `_warn_if_db_ahead_of_head` only caught `psycopg.OperationalError`.
  Non-connection DB errors (e.g. `InsufficientPrivilege` / 42501 if the
  runtime DB user lacks SELECT on `_prisma_migrations`) would propagate
  uncaught and crash startup — contradicting the docstring's
  "informational only, never blocks" guarantee. Widen the catch to
  `psycopg.DatabaseError` so all DB-layer errors are swallowed.

- In the P3009 and P3018 idempotent-recovery paths, the call to
  `_resolve_specific_migration(name)` was not wrapped in its own
  try/except. Being inside an active `except CalledProcessError`
  handler, a new `CalledProcessError` from the resolve call would NOT
  re-enter the same handler — it would propagate out as
  `CalledProcessError`, past `proxy_cli.py`'s `except RuntimeError`,
  crashing startup with an unhandled traceback instead of the intended
  clean `sys.exit(2)`. Wrap both call sites to convert to RuntimeError.

Adds unit tests for both behaviors.
2026-04-21 15:53:07 -07:00
ishaan-berri
a302613eb5
feat(bedrock): add support for bedrock-mantle endpoint (Claude Mythos Preview) (#26196)
* add anthropic.claude-mythos-preview to model_prices_and_context_window.json

* add mantle route to bedrock common_utils: route detection, chat config, messages config dispatch

* add AmazonMantleConfig for bedrock/mantle /chat/completions endpoint

* add AmazonMantleMessagesConfig for bedrock/mantle /messages endpoint

* register AmazonMantleMessagesConfig in __init__.py and lazy imports registry

* add unit tests for bedrock mantle route and config dispatch

* add e2e tests for bedrock mantle: URL, body, SigV4 header, region routing
2026-04-21 15:41:58 -07:00
Yuneng Jiang
9049f37864
[Fix] v2 migration resolver: address Greptile review findings
- Open the psycopg connection in `_warn_if_db_ahead_of_head` with
  autocommit=True. Without it, psycopg3's `with conn` calls COMMIT on
  clean exit, which fails after the `UndefinedTable` (fresh-DB) branch
  left the transaction in an aborted state — crashing first-run startups.

- Wrap the v2 `prisma db push` path in try/except and raise RuntimeError
  on CalledProcessError/TimeoutExpired. Otherwise these propagate past
  proxy_cli.py's `except RuntimeError` as unhandled tracebacks.

- Reword the loop-exhaustion error to cover the non-timeout exit path
  (repeated P3005/P3009/P3018 idempotent-recovery `continue`s), not
  just persistent timeouts.

Adds a unit test for the db_push error wrapping.
2026-04-21 15:34:24 -07:00
ishaan-berri
8a4a775b1b
fix(logging): add litellm_call_id to StandardLoggingPayload and OTel span (#26133)
* add litellm_call_id field to StandardLoggingPayload

* populate litellm_call_id in get_standard_logging_object_payload

* emit litellm.call_id span attribute in OTel integration

* test: litellm_call_id is present in StandardLoggingPayload

* test: litellm.call_id emitted as OTel span attribute

* test: allow litellm. prefix attributes in redacted span validator
2026-04-21 15:24:32 -07:00
Yuneng Jiang
88b1823f51
[Test] Fix setup_database call-signature assertions for v2 flag
Existing tests pinned exact kwargs on `PrismaManager.setup_database`,
but the opt-in v2 resolver added `use_v2_resolver=False` to every call.
Update the three assertions to reflect the new signature.

Fixes:
- TestHealthAppFactory::test_use_prisma_db_push_flag_behavior
- TestHealthAppFactory::test_startup_fails_when_db_setup_fails
2026-04-21 14:45:29 -07:00
yuneng-jiang
7752683e4b
Merge pull request #26185 from BerriAI/litellm_/interesting-wright-958880
[Infra] Add freshness and destructive guards to migration workflow
2026-04-21 14:42:17 -07:00
Yuneng Jiang
ee550e1949
[Test] CI: add v2 migration resolver coverage with local Postgres
Adds end-to-end CI coverage for `--use_v2_migration_resolver` via a new
job `installing_litellm_on_python_v2_migration_resolver`:

- Clones the pytest smoke path from `installing_litellm_on_python` but
  uses a local Postgres sidecar instead of the shared DB to prevent
  collisions with the v1 variant.
- Runs only the new `test_litellm_proxy_server_config_no_general_settings_v2_resolver`
  which spawns the proxy with `--use_v2_migration_resolver` and smoke-tests
  `/health/liveliness` and `/chat/completions`.

Refactors `test_basic_python_version.py`:

- Extracts the proxy spawn + smoke-test body into `_run_proxy_server_smoke_test`
  so the v1 and v2 tests share the same code path.
- The existing `test_litellm_proxy_server_config_no_general_settings` is
  now a thin wrapper that passes no extra args (v1 default, unchanged).
- Adds `..._v2_resolver` variant that passes `--use_v2_migration_resolver`.

The existing `installing_litellm_on_python` / `installing_litellm_on_python_3_13`
jobs filter out the v2 variant via `-k "not v2_resolver"` so they keep
running only against their shared DB, unchanged behavior.
2026-04-21 14:40:11 -07:00
Yuneng Jiang
a16c00e22c
[Feature] Proxy: opt-in v2 migration resolver (--use_v2_migration_resolver)
Default behavior (v1) is unchanged. Users who have seen schema thrashing
during rolling deploys can opt into the v2 resolver with
`--use_v2_migration_resolver`.

Why v2 is safer:
- Runs `prisma migrate deploy` only.
- Recovers from P3005 (baseline) and idempotent P3009/P3018 errors, same
  as v1.
- Never calls `_resolve_all_migrations`, which generates a schema diff
  between the live DB and the shipped schema.prisma and applies it via
  `prisma db execute`. That path bypassed every migration's SQL and was
  the root cause of thrashing when two LiteLLM versions contended for
  the same DB.
- Logs a non-blocking warning when the DB has migrations applied that
  are newer than anything this build ships (ahead-of-HEAD). It does not
  refuse to start — many users have unusual ledger state from past
  thrashing, and blocking startup would be a breaking change.

Also prints a message on startup when the default (v1) resolver is in
use, pointing operators at the opt-in flag.

Adds unit tests covering the v2 fail-fast paths, the stripping of
Prisma-specific query params from DATABASE_URL (needed for psycopg),
the timestamp helpers, and pins the default: v1 still invokes
`_resolve_all_migrations`, v2 must not.
2026-04-21 14:20:35 -07:00
Mateo Wang
df9d6c7da3
Merge pull request #26148 from BerriAI/litellm_fix-bedrock-invoke-allowlist
fix(bedrock): allowlist Bedrock Invoke body fields and filter all anthropic-beta values
2026-04-21 13:22:50 -07:00
shivam
e0cc158860
Merge remote-tracking branch 'upstream/litellm_internal_staging' into litellm_post_call_non_streaming 2026-04-21 13:03:13 -07:00
shin-berri
165c503434
Merge pull request #26150 from BerriAI/litellm_/serene-bohr-4bb54c
[Infra] CI: speed up proxy unit tests and split proxy-utils into its own matrix entry
2026-04-21 12:58:22 -07:00
Yuneng Jiang
5b007add62
[Docs] Fix docstring inaccuracies in run_migration.py
- _find_destructive_statements: add DROP INDEX to the docstring (the
  regex already detects it; only the docstring lagged).
- create_migration: correct the base_branch default documented in the
  docstring from "main" to "litellm_internal_staging".
2026-04-21 12:07:19 -07:00
Yuneng Jiang
b39f210a6c
[Infra] Add freshness and destructive guards to migration workflow
Generating a migration from a stale branch could silently emit DROP
COLUMN for columns the stale branch did not know about, and the
script would write that SQL to a new migration file with no warning.

Adds two guards to ci_cd/run_migration.py:

- Branch freshness check: fetches origin/<base-branch> and exits 3 if
  HEAD is behind. Default base is litellm_internal_staging. New
  flags: --base-branch, --skip-freshness-check.
- Destructive guard: refuses (exit 2) if the generated diff contains
  DROP COLUMN / DROP TABLE / DROP INDEX, unless --allow-destructive
  is passed.

Refusal banners include guidance and an explicit callout instructing
AI agents not to auto-bypass the flags. Also treats Prisma's
"-- This is an empty migration." output as a no-op rather than
writing an empty file.

Updates litellm-proxy-extras/migration_runbook.md with the new
workflow, flag documentation, and agent warnings.
2026-04-21 12:00:23 -07:00
yuneng-jiang
bb46d36bab
Merge pull request #26182 from BerriAI/litellm_budget_spend_counter_alignment
[Fix] Align user and org budget spend checks with atomic counter pattern
2026-04-21 11:46:25 -07:00
shivam
62c2c553d7
Merge remote-tracking branch 'upstream/litellm_internal_staging' into litellm_post_call_non_streaming 2026-04-21 11:45:26 -07:00
SwiftWinds
11b776935d chore: make uv newer than 0.10 allowable 2026-04-21 11:39:11 -07:00
SwiftWinds
6da9ee9511 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_fix-bedrock-invoke-allowlist 2026-04-21 11:38:12 -07:00
SwiftWinds
583bdd34a2 fix(bedrock): allowlist Bedrock Invoke body fields and filter all anthropic-beta values
Two fail-safes for the /v1/messages → Bedrock Invoke pass-through so new
Anthropic-only extensions Claude Code starts sending can't reach Bedrock
and trigger a 400 "Extra inputs are not permitted":

1. Top-level body fields are filtered to a typed allowlist. New
   `BedrockInvokeAnthropicMessagesRequest` TypedDict (in
   `litellm/types/llms/bedrock.py`) captures the Bedrock Invoke Anthropic
   Messages body schema; the runtime allowlist is derived from its
   `__annotations__` so the type and the filter can't drift. Anchored to
   the AWS reference page in docstrings + transform comment. An
   exact-set test pins the resolved allowlist so any future edit forces
   conscious review.

   Drops context_management, output_config, speed, mcp_servers,
   container, inference_geo, internal litellm_metadata, and any future
   Anthropic addition. output_format stays as an active inline-schema
   conversion (not just a strip).

2. The anthropic-beta header list is filtered + transformed against the
   bedrock mapping for ALL betas, not just auto-injected ones. The
   previous code union'd user-provided betas back in unfiltered, so a
   client on a new Anthropic-direct beta (e.g. advisor-tool-…,
   context-management-…) could still pin the request to fail. In a proxy
   context the client can't know the backend is Bedrock; the provider
   mapping is authoritative. User-provided drops are logged at WARNING
   so intentional overrides leave a breadcrumb.

Updates one existing test that happened to assert on the old buggy
pass-through (it used output-128k-2025-02-19, which is null in the
bedrock mapping and would 400 at runtime); rewrote it against a
bedrock-supported beta.

Scope: messages/invoke only. The same user-beta bypass exists in
chat/invoke but that's a different code path with different
user-expectation trade-offs — follow-up.
2026-04-21 11:26:15 -07:00
shin-berri
7cc22dbe19
Merge pull request #26047 from BerriAI/litellm_ui-api-double-prefix-a8a3
[Fix] CI: e2e_ui_testing tests stale bundle on Ubuntu (cp -r merge semantics)
2026-04-21 10:42:32 -07:00
Yuneng Jiang
c2b7c4bfcd
fix: skip personal budget check in MaxBudgetLimiter for team-key requests 2026-04-21 10:38:08 -07:00
Yuneng Jiang
7656e26331
fix: align user and org spend checks with atomic counter pattern
Brings user personal budget and organization budget enforcement
in line with the existing key and team patterns, which already
read spend from the atomic cross-pod Redis counter.
2026-04-21 10:21:29 -07:00
Yuneng Jiang
4b3f5d7f81
[Fix] conftest: flush cache instances and warn on silent skips
Addresses review feedback on the snapshot approach:

1. Class-instance mutable state
   The snapshot only covers primitives + collections + None. Class
   instances (DualCache, LLMClientCache) weren't reset between tests,
   so in-place cache mutations could leak. Can't deepcopy these — they
   hold thread locks — but they expose flush_cache(). Collect every
   module attribute whose value implements flush_cache() at conftest
   import, and invoke it per-test alongside the snapshot restore.

2. Silent skips are now warnings
   _snapshot_mutable_state and _restore_mutable_state previously
   swallowed exceptions, so if a future attr gained a property without
   a setter (or other non-round-trippable state), an isolation gap
   would have no signal. Emit warnings.warn on each failure path.

3. Docstring
   Explicitly documents what IS and IS NOT reset, and tells authors to
   use monkeypatch.setattr() for in-place mutations of instances
   without flush_cache() (ProxyLogging, JWTHandler, etc.).
2026-04-20 22:19:36 -07:00
Yuneng Jiang
0f5d503169
fix(ci): make e2e_ui_testing actually test the freshly built UI bundle
The Build UI from source step used:

    cp -r out/ ../../litellm/proxy/_experimental/out/

GNU cp (CircleCI's Ubuntu image, coreutils 8.32) interprets this as
copy the source directory as a CHILD of the destination when the
destination already exists — so the command silently created
litellm/proxy/_experimental/out/out/ instead of replacing the served
bundle at litellm/proxy/_experimental/out/*.

The proxy continued serving whatever bundle was checked in, so every
e2e_ui_testing run between this job's introduction (d09d98a70a,
2026-04-08) and the bundle-rebuild commit (de790fd273, 2026-04-18) was
effectively testing a STALE bundle — not the fresh build. That is why
the double-prefix regression (NEXT_PUBLIC_BASE_URL="ui/" combined with
networking.tsx reading the env var) was never caught in CI even though
the source contained the trigger the whole time: the bundle the proxy
served never picked up the source change.

Replace cp -r with rm + mv so the destination is cleanly swapped.

Verified end-to-end on an Ubuntu 22.04 / GNU coreutils 8.32 container:
- Before fix: fresh build has 9 "ui/" literals in chunks; after cp,
  _experimental/out/*  still has 0 (stale); _experimental/out/out/ is a
  nested dir the proxy does not serve.
- After fix: _experimental/out/*  has 9 "ui/" literals — the proxy now
  serves the freshly built (broken, in this repro) bundle, so
  globalSetup fails at login and every spec is blocked. Removing the
  bug from .env.production and rebuilding brings the count back to 0
  and the suite passes.

No spec changes, no fixtures, no new infrastructure. The existing
Playwright suite already catches this class of regression via the
login flow in globalSetup; it just needs the CI to actually hand it
the freshly built bundle.
2026-04-20 22:09:54 -07:00
Yuneng Jiang
5411ebedae
[Fix] conftest snapshot: also reset scalar module attributes
The previous snapshot only tracked list/dict/set values. Tests mutate
scalar module attrs too — master_key, premium_user, prisma_client — and
importlib.reload used to reset those implicitly. Under the snapshot
approach they were leaking between tests, so test_active_callbacks
failed in CI with "No api key passed in." once an earlier test left
master_key set to sk-1234.

Expand the snapshot to cover primitives (str/int/float/bool/bytes/tuple)
and None-valued attributes. Complex object instances are still skipped
to avoid deepcopy issues.
2026-04-20 21:03:07 -07:00
shivam
6beba97d20
test(bedrock_guardrails): assert apply_guardrail maps response to OUTPUT source
Add regression tests that mock make_bedrock_api_request and verify
input_type=request uses source=INPUT with user messages, and
input_type=response uses source=OUTPUT with synthetic ModelResponse.

Made-with: Cursor
2026-04-20 19:53:49 -07:00
shivam
c770756cf3
fix(bedrock_guardrails): route apply_guardrail to OUTPUT for response scans
BedrockGuardrail.apply_guardrail hardcoded source="INPUT" regardless of the
input_type parameter. On the non-streaming post-call path (unified_guardrail
-> OpenAIChatCompletionsHandler.process_output_response -> apply_guardrail),
the model response text was sent to Bedrock as INPUT, so guardrail policies
configured for Output (e.g. PII/NAME blocking) returned action=NONE and the
response passed through unblocked. The streaming path was unaffected because
it calls make_bedrock_api_request(source="OUTPUT", ...) directly.

Map input_type to the correct Bedrock source ("request" -> INPUT,
"response" -> OUTPUT) and build a synthetic ModelResponse for the OUTPUT
path so _create_bedrock_output_content_request produces the correct payload.

Made-with: Cursor
2026-04-20 19:42:51 -07:00
Yuneng Jiang
ccf928361b
[Infra] Speed up proxy unit tests by replacing litellm reload with state snapshot
tests/proxy_unit_tests/conftest.py was calling importlib.reload(litellm) in an
autouse function-scoped fixture, which cost ~17s per test because it re-ran
the full litellm __init__ import chain. With 400+ proxy unit tests, this was
the single biggest driver of CI wall time — 18 of the top 20 slowest durations
in a typical run were just the 17s fixture setup.

Replace the reload with a snapshot-and-restore approach: snapshot the mutable
lists/dicts/sets on litellm and litellm.proxy.proxy_server once at conftest
import, then deep-copy that snapshot back before each test. Callback lists,
caches, router state, etc. still get reset between tests, but the expensive
import chain only runs once per worker.

Local measurement on test_proxy_utils.py: 188 tests in 3.50s (previously took
~15 minutes of CI wall time on a single worker).
2026-04-20 17:59:05 -07:00
Krrish Dholakia
bd3ee987b3 fix(adaptive_router): bound owner cache, drop PK from upsert update, redact PII
Some checks are pending
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, 30, 8) (push) Waiting to run
Unit Tests: Security / security (push) Waiting to run
- _owner_cache now opportunistically sweeps expired entries past
  _OWNER_CACHE_SWEEP_THRESHOLD live entries. Previously sessions that never
  came back piled up forever.
- flush_session_to_db strips session_id/router_name/model_name from the update
  payload. Prisma rejects writes to @@id fields.
- record_turn no longer persists last_user_content / last_assistant_content /
  tool_call_history / pending_tool_calls. Those are needed only in-memory for
  the next turn's signal detection; writing user prompts and tool payloads to
  the DB would store PII for every conversation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 17:53:52 -07:00
Krrish Dholakia
bcc093d8c5 fix(adaptive_router): enforce satisfaction gate, stop false-flagging empty tool output
- SessionState now carries clean_credit_awarded + last_processed_turn (matching
  the DB schema). Satisfaction only fires once per session AND only after
  MIN_TURNS_FOR_CLEAN_CREDIT turns of context — early "thanks" no longer
  inflates alpha.
- _detect_failure no longer treats empty content as failure. Many tools
  legitimately return empty output (zero-result searches, silent bash);
  penalizing those corrupted the bandit posterior. Only is_error fires now.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 17:47:25 -07:00