Skip to content

ci: run a local fake OpenAI endpoint instead of the shared Railway mock#30695

Merged
mateo-berri merged 1 commit into
litellm_internal_stagingfrom
litellm_ci_fake_openai_mock
Jun 18, 2026
Merged

ci: run a local fake OpenAI endpoint instead of the shared Railway mock#30695
mateo-berri merged 1 commit into
litellm_internal_stagingfrom
litellm_ci_fake_openai_mock

Conversation

@mateo-berri

@mateo-berri mateo-berri commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

Relevant issues

Several CI jobs run the proxy against a model whose api_base is a shared "fake OpenAI endpoint" hosted on Railway (exampleopenaiendpoint-production.up.railway.app) so the E2E runs get canned responses without paying for or depending on a live provider. When that single deployment goes down, every one of those jobs fails with 404 Application not found even though nothing in the PR is broken; the whole repo is coupled to the uptime of one free external service. We hit exactly this on #30690, where the same outage reddened a batch of unrelated jobs.

Linear ticket

N/A

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have added meaningful tests
  • My PR passes all unit tests on make test-unit
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have requested a Greptile review by commenting @greptileai and received a Confidence Score of at least 4/5 before requesting a maintainer review

CI (LiteLLM team)

CI status guideline:

  • 50-55 passing tests: main is stable with minor issues.
  • 45-49 passing tests: acceptable but needs attention
  • <= 40 passing tests: unstable; be careful with your merges and assess the risk.
  • Branch creation CI run
    Link:

  • CI run for the last commit
    Link:

  • Merge / cherry-pick CI run
    Links:

Screenshots / Proof of Fix

The new server stands in for the live endpoint; here it is serving the shapes the E2Es rely on (run uv run --no-sync python tests/_fake_openai_endpoint_server.py --port 8190 first):

$ curl -s http://127.0.0.1:8190/health
ok

$ curl -s -X POST http://127.0.0.1:8190/v1/chat/completions \
    -H 'Content-Type: application/json' \
    -d '{"model":"gpt-5-mini","messages":[{"role":"user","content":"hi"}]}'
{"id":"chatcmpl-...","object":"chat.completion","model":"gpt-5-mini","choices":[{"index":0,"message":{"role":"assistant","content":"Hello! This is a mock response from the fake OpenAI endpoint."},"finish_reason":"stop"}],"usage":{"prompt_tokens":20,"completion_tokens":20,"total_tokens":40}}

$ curl -s -o /dev/null -w 'HTTP %{http_code}\n' -X POST http://127.0.0.1:8190/v1/chat/completions \
    -H 'Content-Type: application/json' \
    -d '{"model":"429","messages":[{"role":"user","content":"hi"}]}'
HTTP 429

$ curl -s -N -X POST http://127.0.0.1:8190/v1/completions \
    -H 'Content-Type: application/json' \
    -d '{"model":"x","stream":true,"stream_options":{"include_usage":true},"prompt":"hi"}'
data: {"id":"cmpl-...","object":"text_completion","choices":[{"text":"Hello! ...","index":0,"logprobs":null,"finish_reason":null}]}
data: {"id":"cmpl-...","object":"text_completion","choices":[{"text":"","index":0,"logprobs":null,"finish_reason":"stop"}]}
data: {"id":"cmpl-...","object":"text_completion","choices":[],"usage":{"prompt_tokens":20,"completion_tokens":20,"total_tokens":40}}
data: [DONE]

The real end-to-end proof is the CI run itself: the eight affected jobs should pass with the live Railway endpoint completely out of the loop. Branch-creation and last-commit CI links go in the section above once they finish.

Type

🚄 Infrastructure

Changes

Adds tests/_fake_openai_endpoint_server.py, a small canned-response OpenAI-shaped server (Starlette) covering chat completions, text completions, embeddings, streaming with optional usage chunks, and the one behavioral special case the old hosted mock had: a request whose model is 429 returns HTTP 429 so rate-limit and cooldown tests still trip. Usage is non-zero and self-consistent (20/20/40) so spend and cost-tracking code paths run for real; the spend-accuracy E2E derives its expected total from each response's own usage, so the absolute numbers don't need to match the old endpoint.

Adds a reusable start_fake_openai_endpoint CircleCI command that launches the server on host port 8190 and waits until healthy, then wires it into the eight jobs that depended on the Railway endpoint: build_and_test, litellm_router_testing, db_migration_disable_update_check, proxy_logging_guardrails_model_info_tests, proxy_spend_accuracy_tests, proxy_multi_instance_tests, proxy_store_model_in_db_tests, and proxy_build_from_pip_tests. Machine-executor jobs reach it from their proxy container via FAKE_OPENAI_API_BASE=http://host.docker.internal:8190; the docker-executor litellm_router_testing job runs it in-container and points at http://127.0.0.1:8190. The example configs those jobs mount now resolve api_base from os.environ/FAKE_OPENAI_API_BASE instead of hardcoding the Railway URL.

Two things are deliberately left alone. The intentionally malformed fallback URL in proxy_server_config.yaml (...railway.appxxxx/) stays as-is so the fallback test still has a failing upstream to fall back from. And nothing here touches the record/replay (VCR) proxy on port 8090 or its redis cassette store; the fake endpoint is a separate process on 8190 that real-provider traffic never reaches, so the cassettes can't be affected.


Note

Low Risk
Changes are limited to CI wiring, test fixtures, and example configs; production proxy behavior is unchanged unless operators set FAKE_OPENAI_API_BASE.

Overview
Replaces the shared Railway fake OpenAI host with a job-local mock so proxy E2E and router tests no longer fail when that external service is down.

Adds tests/_fake_openai_endpoint_server.py (Starlette on port 8190) with canned chat/text/embedding responses, streaming + usage, and HTTP 429 when model is 429. CircleCI gets a reusable start_fake_openai_endpoint step; eight jobs start it and set FAKE_OPENAI_API_BASE (127.0.0.1:8190 in-container, host.docker.internal:8190 for proxy Docker runs).

CI example configs and proxy_server_config.yaml switch fake-model api_base from the Railway URL to os.environ/FAKE_OPENAI_API_BASE. test_router_text_completion_client reads the same env with the old URL as fallback. The deliberately broken Railway URL for fallback testing is unchanged.

Reviewed by Cursor Bugbot for commit afd66a5. Bugbot is set up for automated code reviews on this repo. Configure here.

Several CI jobs run the proxy against a model whose api_base is a shared
"fake OpenAI endpoint" hosted on Railway
(exampleopenaiendpoint-production.up.railway.app) so the E2E runs return
canned responses without paying for or depending on a live provider. When
that single deployment is down, every one of those jobs fails with
"404 Application not found" even though nothing in the PR is broken; the
whole repo is coupled to the uptime of one free external service.

This adds tests/_fake_openai_endpoint_server.py, a small canned-response
OpenAI-shaped server (chat, text, embeddings, streaming with usage, and the
"429" rate-limit special case), and a reusable start_fake_openai_endpoint
CircleCI command that runs it on host port 8190 and waits until healthy. The
affected jobs now inject FAKE_OPENAI_API_BASE pointing at the local server,
and the example configs they mount resolve api_base from that env var. The
intentionally bad fallback URL in proxy_server_config.yaml is left untouched
so the fallback test still exercises a failing upstream.

Wired into build_and_test, litellm_router_testing,
db_migration_disable_update_check, proxy_logging_guardrails_model_info_tests,
proxy_spend_accuracy_tests, proxy_multi_instance_tests,
proxy_store_model_in_db_tests, and proxy_build_from_pip_tests.
@mateo-berri mateo-berri marked this pull request as ready for review June 17, 2026 23:01
@mateo-berri mateo-berri requested a review from a team June 17, 2026 23:01
@codecov

codecov Bot commented Jun 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@greptile-apps

greptile-apps Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR eliminates CI flakiness caused by the shared Railway fake-OpenAI deployment by introducing a local Starlette/uvicorn mock server (tests/_fake_openai_endpoint_server.py) that serves canned chat, text-completion, embedding, and streaming responses, then wires it into the eight CI jobs that depended on the Railway endpoint.

  • The new server correctly mirrors the only behavioral special-case from the old hosted mock: requests with model: "429" return HTTP 429, preserving rate-limit and cooldown test coverage. Usage tokens are non-zero and self-consistent so spend-tracking code paths execute fully.
  • All eight CI jobs are updated consistently: machine-executor jobs start the server on the host and pass FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 into their Docker containers; the docker-executor litellm_router_testing job sets FAKE_OPENAI_API_BASE: http://127.0.0.1:8190 at the job level. Every job runs uv sync before start_fake_openai_endpoint, ensuring starlette and uvicorn are present.
  • The intentionally malformed ...railway.appxxxx/ URL in proxy_server_config.yaml is correctly left alone so the fallback-upstream test still has a broken endpoint to fall back from.

Confidence Score: 5/5

Safe to merge — the change only affects CI infrastructure and test config; no production code paths are touched.

The mock server is a clean Starlette app exempt from litellm's handler-reuse rule (test-only shim rule applies). All eight CI jobs have uv sync in place before the fake endpoint starts, the health-check loop gives 30 seconds for startup, and the host-networking split (127.0.0.1 for docker-executor, host.docker.internal for machine-executor) is applied correctly everywhere. The intentionally malformed Railway URL in proxy_server_config.yaml is left untouched. The only existing test touched uses the env var with the old URL as a safe fallback and does not weaken coverage.

No files require special attention.

Important Files Changed

Filename Overview
tests/_fake_openai_endpoint_server.py New Starlette/uvicorn-based canned-response mock server covering chat completions, text completions, embeddings, streaming with optional usage chunks, and the 429 rate-limit trigger; clean and self-contained
.circleci/config.yml Adds start_fake_openai_endpoint reusable command and wires it into 8 jobs; machine-executor jobs pass host.docker.internal:8190 to Docker containers, docker-executor litellm_router_testing sets 127.0.0.1:8190 at job level; all jobs have uv sync before the fake server starts
proxy_server_config.yaml Replaces hardcoded Railway URLs with os.environ/FAKE_OPENAI_API_BASE on all applicable models; the intentionally malformed railway.appxxxx/ fallback URL is correctly left untouched
tests/local_testing/test_router.py Existing router test updated to read api_base from FAKE_OPENAI_API_BASE env var with Railway URL as fallback; does not weaken test coverage
litellm/proxy/example_config_yaml/otel_test_config.yaml All 5 Railway URL references (including the 429-trigger model and bedrock/*) replaced with os.environ/FAKE_OPENAI_API_BASE
docker/build_from_pip/litellm_config.yaml Single Railway URL replaced with env-var reference; proxy_build_from_pip_tests passes FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 to the container

Reviews (1): Last reviewed commit: "ci: run a local fake OpenAI endpoint ins..." | Re-trigger Greptile

@mateo-berri

Copy link
Copy Markdown
Collaborator Author

bugbot run


Generated by Claude Code

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit afd66a5. Configure here.

@mateo-berri mateo-berri merged commit 556e8f8 into litellm_internal_staging Jun 18, 2026
125 checks passed
@mateo-berri mateo-berri deleted the litellm_ci_fake_openai_mock branch June 18, 2026 00:01
mateo-berri added a commit that referenced this pull request Jun 20, 2026
…ndpoint (#30900)

* test: point router/completion/triton tests at the local fake OpenAI endpoint

The shared Railway-hosted mock (exampleopenaiendpoint-production.up.railway.app)
takes down unrelated CI jobs whenever it is unreachable. #30695 moved the mounted
proxy configs onto a job-local fake server but left these in-Python api_base
literals pointing at the dead host, so litellm_router_testing, local_testing_part1,
local_testing_part2 and llm_translation_testing still fail with a 404
"Application not found" when Railway is down

Resolve the api_base from FAKE_OPENAI_API_BASE (default http://127.0.0.1:8190)
through a shared helper, auto-start the canned server from the local_testing and
llm_translation conftests when nothing is already serving, and extend the server
with a Triton embeddings route and a slow-endpoint delay so the triton and
latency-timeout tests run fully offline. The deliberately broken fallback URL is
left as-is so fallback handling still has a failing upstream

* fix: ignore non-loopback FAKE_OPENAI_API_BASE so the local mock is used in CI

* fix: drop 0.0.0.0 from loopback hosts, an unreliable client connect target

* fix(tests): keep fake OpenAI mock alive across xdist workers

ensure_fake_openai_endpoint registered atexit on the worker that spawned
the subprocess, so under -n 4 the first worker to drain its queue would
terminate the shared mock while siblings were still hitting it. Detach
the child via start_new_session and drop the per-worker teardown; reuse
on /health handles re-runs and CI containers clean up themselves
Sameerlite added a commit that referenced this pull request Jun 22, 2026
* fix(anthropic): price and surface response service_tier in cost tracking (#30558)

* feat: add dev and wildcard proxy configs for local testing (#30556)

* fix(proxy): list public team model name in /v1/models (#30588)

* fix(proxy): optionally surface public team model name in /v1/models

Behind general_settings.use_team_public_model_name (default False). When
enabled, /v1/models and /models surface the public team_public_model_name
for team-scoped (BYOK) models instead of the internal routing key
model_name_{team_id}_{uuid} -- consistent with /v1/model/info and
OpenAI-compatible. Off by default so the listing's model ids stay
backward-compatible for callers that scripted against the internal name;
routing by the internal name is unchanged regardless of the flag.

Presentation-layer only: access-group, auth, and routing semantics are
unchanged; non-team models are pass-through.

* fix(proxy): default team model listings to public names

* test(proxy): cover team model listing metadata

* test(proxy): cover empty team listing deployments

* refactor(proxy): simplify team model listing translation

* fix(proxy): resolve public team model name on GET /v1/models/{id}

The listing endpoints advertise team_public_model_name, but the retrieve
endpoint validated and looked up by the raw id, so a public name 404'd.
Resolve the public name back to the internal routing key (scoped to the
caller's accessible models so colliding names never cross teams), look up
by it, and echo the public name back as the response id.

* test(proxy): cover public-name resolution on model retrieve

* refactor(proxy): extract team model-name translation into TeamModelNameTranslator

Move the team-scoped (BYOK) listing/retrieve name translation out of
proxy_server.py into a dedicated common_utils module. Static methods with
general_settings injected so the logic is unit-testable without globals and
proxy_server.py stays thin.

* refactor(proxy): use TeamModelNameTranslator in model_list and model_info

* test(proxy): target TeamModelNameTranslator for model-name translation

* fix(proxy): type create_model_info_response return as dict[str, object]

* fix(proxy): keep internal routing key for team model listing metadata lookup

Add listing_entries returning (public response id, internal lookup id) so
include_metadata=true resolves fallbacks against the routing key the router
indexes by, instead of the translated public name (which never matches).

* fix(proxy): build /v1/models metadata from internal key, show public id

* test(proxy): cover team listing fallback metadata via internal key

* fix(proxy): use builtin dict generics in create_model_info_response (UP006)

---------

Co-authored-by: Tushar More <[email protected]>
Co-authored-by: Ishaan Jaffer <[email protected]>

* ci: drop mypy entirely, standardize type checking on basedpyright (#30648)

* ci: drop redundant mypy type-check gate, standardize on basedpyright

Type checking ran both mypy (via the pydantic.mypy plugin) and basedpyright.
pydantic v2 emits dataclass_transform, so basedpyright understands models
natively with no plugin, and its gated rules already cover what the mypy pass
caught (no-untyped-def, no-any-return, valid-type, import-not-found all map to
basedpyright equivalents). Running both meant two checkers, two budgets, and a
plugin only mypy could load.

This removes the mypy type-check gate: the lint-mypy/lint-mypy-budget-update
Makefile targets, the CI MyPy step, mypy-code-budget.json, the budget-ratchet
entry, and the vestigial [tool.mypy] pydantic plugin block (the gating pass used
litellm/mypy.ini, which never loaded the plugin). type_check_gate.py is
specialized to basedpyright since the mypy parsing path is now unused.

mypy stays a dev dependency because the Any-discipline gate
(scripts/check_any_discipline.py) imports it as a library to detect Any-typed
values; it is no longer run as a type checker.

* ci: remove the Any-discipline gate, rely on basedpyright's reportAny

The Any-discipline gate (scripts/check_any_discipline.py) was the last consumer
of mypy: it imported mypy as a library to detect values whose inferred type
contains Any, gated per-file against any-discipline-budget.json. basedpyright
already reports the same class of finding through reportAny/reportExplicitAny,
which are gated tree-wide in basedpyright-code-budget.json, so the separate gate
(and the mypy dependency behind it) is redundant.

Removes the gate end to end: check_any_discipline.py and its test, the
any-discipline CI job, the lint-any/lint-any-budget-update Makefile targets,
any-discipline-budget.json, litellm/mypy.ini, the .mypy_cache_any references,
and mypy from the dev dependencies. budget_ratchet_check.py drops the
any-discipline entry and the now-unused zero-floor mechanism (rewritten as a
comprehension). check_type_discipline.py drops the any-ok suppression token,
since # any-ok suppressed only the deleted gate; the 134 now-orphaned
# any-ok comments across 14 files are stripped (they never affected
basedpyright, which uses # pyright: ignore).

uv.lock is intentionally left untouched: uv still considers it consistent with
the mypy-removed pyproject (uv lock --check and uv sync --frozen both pass), and
a relock bumps 30+ unrelated packages because of the moving exclude-newer window.
A future intentional relock will prune the now-unreferenced mypy entry.

* build: relock to drop mypy from uv.lock

CI's uv 0.10.9 honors the repo's exclude-newer window and correctly flags the
lockfile as out of sync once mypy leaves pyproject; my earlier local uv 0.8.17
could not parse exclude-newer and silently passed --check. Relocking with the
pinned CI version removes only mypy and its transitive librt, with no other
version changes.

* feat(guardrails): surface OpenAI moderation violation_categories on guardrail traces (#30659)

The OpenAI moderation guardrail (and the ai-platform-moderation guardrail
built on it) stamped the whole moderation model response into the guardrail
trace as guardrail_response. That blob carries the full category_scores map
plus categories and category_applied_input_types, which on OTEL backends that
index span attributes (for example ELK, which caps indexed attribute values at
1024 chars) overflows the limit and gets truncated, so the violated categories
cannot be reliably searched.

Extract the flagged category names from the moderation response and pass them
through tracing_detail to add_standard_logging_guardrail_information_to_request_data,
mirroring the Bedrock hook. Both the legacy and v2 OTEL integrations already
read violation_categories off the standard logging guardrail information and
emit it as a short, queryable guardrail_violation_categories attribute, so
dashboards can group and filter by violation category without parsing the large
guardrail_response blob.

Resolves LIT-3801

* fix(proxy): resolve list files credentials from team BYOK deployments (#30495)

* fix(proxy): resolve list files credentials from team BYOK deployments

GET /v1/files without target_model_names now prefers the team's own
deployment (model_info.team_id) over shared global provider keys, so JWT
team auth lists files against the correct upstream account.

Co-authored-by: Cursor <[email protected]>

* fix(proxy): scope list files credential lookup to team allowlist

Remove the unrestricted deployment scan that could leak global provider
keys to teams without access, normalize all-proxy-models to the team-scoped
model list, and fix TID251 violations by using dict instead of Dict/Any.

Co-authored-by: Cursor <[email protected]>

---------

Co-authored-by: Cursor <[email protected]>

* feat(proxy): add --max_requests_before_restart_jitter to stagger worker restarts (#30601)

Setting --max_requests_before_restart alone recycles every worker at almost the
same time once they have served a similar number of requests, which under
sustained load can drop a whole pod's capacity at once roughly every 7-10 days.

This exposes a jitter knob that adds a random amount in [0, jitter] to the
restart threshold per worker so restarts are staggered. It maps to uvicorn's
limit_max_requests_jitter and gunicorn's max_requests_jitter. uvicorn only
gained limit_max_requests_jitter in 0.41.0 while litellm still allows
uvicorn>=0.33.0, so the uvicorn path feature-detects the parameter via the
Config signature and warns instead of crashing on older versions. The flag has
no effect without --max_requests_before_restart, so the kwarg is not forwarded
in that case and a warning is printed on both the uvicorn and gunicorn paths.

Resolves LIT-3774

* fix(health): correct bedrock embedding health checks (#30583)

* fix(health): correct bedrock embedding health checks

Health checks for Bedrock embedding deployments failed in two ways. A
deployment configured without an explicit model_info.mode was probed as
chat, so max_tokens was injected and Bedrock embeddings rejected it with
400 "extraneous key [max_tokens]". Separately, stripping the bedrock/
routing prefix dropped the provider, so a cross-region inference-profile
id like us.cohere.embed-v4:0 failed downstream with "LLM Provider NOT
provided".

Resolve the deployment mode from the model cost map (which understands
the bedrock/ and us./eu./apac. prefixes) before deciding whether to
inject max_tokens, and pin custom_llm_provider to bedrock when stripping
the prefix so the bare model id still resolves. ahealth_check now accepts
any string mode so the resolved embedding mode routes the probe to the
embedding handler.

* fix(health): preserve explicit custom_llm_provider on bedrock probe

The bedrock prefix-strip pinned custom_llm_provider to bedrock
unconditionally, so a deployment that set custom_llm_provider:
bedrock_converse had it overwritten at health-check time and the probe
hit the Invoke endpoint instead of Converse, a different request format
that can report a spurious failure. Only fill in bedrock when the
deployment left the provider blank, which still resolves bare
cross-region ids like us.cohere.embed-v4:0 while leaving an explicit
provider untouched.

* test(health): assert resolved mode reaches the ahealth_check probe

The existing tests check _resolve_health_check_mode and the params builder
in isolation, but nothing verified that _run_model_health_check actually
threads the resolved mode into litellm.ahealth_check. Without that, a
refactor that probed with model_info.get("mode") again would reintroduce
the chat fallback for embedding deployments while every test stayed green.
This drives _run_model_health_check with a bedrock embedding deployment and
asserts the probe is called with mode=embedding and the embedding params.

* fix(health): resolve probe mode once for reasoning_effort and audio_speech

The reasoning_effort and audio_speech branches read model_info.mode
directly, so an embedding deployment declared without an explicit mode (the
case this PR targets) was still treated as chat-like: a configured
health_check_reasoning_effort got injected into the embedding probe, which
embeddings reject as an unknown field, and an auto-detected audio_speech
deployment never had its voice set. Resolve the effective mode once from the
cost map and reuse it for the max_tokens, reasoning_effort, and audio_speech
decisions so they all agree with the mode threaded into ahealth_check.

* test: harden remaining pass-through CI flakes (image-gen spend poll, ruby assistants timeout) (#30685)

* test(proxy): poll for image-gen spend instead of a fixed 5s sleep

test_key_info_spend_values_image_generation failed once on litellm_internal_staging
(pipeline 82282) with "spend did not increase on an identical repeat image call"
(assert 0.24966 > 0.24966). The test made the second image call, slept 5s, then
read the key's spend once. Response caching is commented out in
proxy_server_config.yaml and no sibling test enables it, so the likely cause is
async/batched spend logging not having flushed the repeat call's cost within 5s,
which the build_and_test job aggravates by running every tests/test_*.py against
one shared proxy under pytest -n 4.

Poll the key's spend for up to 60s and break as soon as it grows. This removes
the timing flake while preserving the canary: if the repeat were genuinely
unbilled (for example the proxy response cache being on), spend never grows, the
poll times out, and the assertion still fails.

* test(pass_through): raise ruby assistants client request_timeout to 600s

The streaming assistants example in openai_assistants_passthrough_spec.rb hit
Net::ReadTimeout on litellm_internal_staging (pipeline 82280), failing at roughly
125s which is ruby-openai's default request_timeout of 120s. An assistants run
with the code_interpreter tool can occasionally take longer than that to stream
its first content back through the pass-through.

Raise the client's request_timeout to 600s, matching the 600s timeout the Python
pass-through e2e tests already use, so a slow-but-healthy streaming run no longer
trips the default read timeout.

* test(pass_through): harden vertex spendlog poll against transient empty reads (#30683)

test_basic_vertex_ai_pass_through_with_spendlog failed intermittently on
litellm_internal_staging (pipelines 82155, 82196, 82209, 82230) with "Spend
should be greater than before after 120s". Spend logging is async and batched,
so the pass-through call's cost sometimes had not landed within the 120s poll
window; one run ended on spend_after 0.0 because the final /global/spend/logs
read returned nothing and "or 0.0" recorded that as zero spend.

Widen the poll window to 240s and skip a transient empty read instead of
treating it as 0.0, so a momentary endpoint hiccup on the last poll no longer
fails an otherwise-billed call. The spend_after > spend_before assertion is
unchanged, so a genuinely unbilled call still fails the test

* fix(cost): stop non-string service_tier from silently dropping cost tracking (#30690)

completion_cost read service_tier straight from the request optional_params
and called service_tier.lower() on it, so a non-string value (dict/int/list,
reachable via allowed_openai_params/drop_params) raised AttributeError.
_response_cost_calculator swallowed that and returned response_cost=None, so
the request's cost was silently lost.

The isinstance guard alone is not enough: a surviving dict would crash again
downstream in _get_service_tier_cost_key, which also calls .lower(). A
request-level service_tier is only meaningful for pricing when it is a concrete
billable tier string, so coerce any non-string value to None and defer to the
tier the provider reports on the response usage, the same way "auto" already
does.

Adds a regression test driving a dict service_tier through completion_cost; it
raises AttributeError before the fix and prices at the served tier after.

* feat(proxy): warn at startup when custom_auth skips common_checks enforcement (#30665)

When general_settings.custom_auth is configured but custom_auth_run_common_checks
is not set, project/team/org enforcement (budgets, model-level rate limits, and
model-access lists) silently does nothing for custom-auth requests, since the
centralized common_checks gate returns early for custom auth. Emit a startup
warning pointing operators at the flag so the misconfiguration is visible instead
of failing silently.

* fix(pod_lock): release cron lock by matching async_set_cache JSON encoding (#30600)

acquire_lock stores the pod_id through async_set_cache, which JSON-encodes
the value, so Redis holds the quoted string "<pod_id>". release_lock's Lua
compare-and-delete compared the raw pod_id, so the equality check never
matched and the lock was never deleted; it only cleared on TTL expiry. That
stalled the spend-update drain whenever the leader pod restarted, letting the
litellm_daily_*_spend_update_buffer lists grow unbounded in Redis.

Compare against json.dumps(self.pod_id) so the release matches the stored
value. The GET+DEL fallback already round-trips through async_get_cache and is
unaffected.

Co-authored-by: Claude <[email protected]>

* ci: run a local fake OpenAI endpoint instead of the shared Railway mock (#30695)

Several CI jobs run the proxy against a model whose api_base is a shared
"fake OpenAI endpoint" hosted on Railway
(exampleopenaiendpoint-production.up.railway.app) so the E2E runs return
canned responses without paying for or depending on a live provider. When
that single deployment is down, every one of those jobs fails with
"404 Application not found" even though nothing in the PR is broken; the
whole repo is coupled to the uptime of one free external service.

This adds tests/_fake_openai_endpoint_server.py, a small canned-response
OpenAI-shaped server (chat, text, embeddings, streaming with usage, and the
"429" rate-limit special case), and a reusable start_fake_openai_endpoint
CircleCI command that runs it on host port 8190 and waits until healthy. The
affected jobs now inject FAKE_OPENAI_API_BASE pointing at the local server,
and the example configs they mount resolve api_base from that env var. The
intentionally bad fallback URL in proxy_server_config.yaml is left untouched
so the fallback test still exercises a failing upstream.

Wired into build_and_test, litellm_router_testing,
db_migration_disable_update_check, proxy_logging_guardrails_model_info_tests,
proxy_spend_accuracy_tests, proxy_multi_instance_tests,
proxy_store_model_in_db_tests, and proxy_build_from_pip_tests.

* ci(windows): pin uv to Python 3.11 so it ignores the preinstalled 3.14 (#30704)

* feat(ui): migrate models page to App Router path route (#30677)

* feat(ui): migrate models page to App Router path route

Cut the Models + Endpoints page over from the legacy ?page=models switch
in (dashboard)/page.tsx to a path route at (dashboard)/models-and-endpoints.
Adding the MIGRATED_PAGES entry repoints the sidebar link and redirects old
?page=models bookmarks to /ui/models-and-endpoints.

ModelsAndEndpointsView already sourced identity from useAuthorized() and its
own data via useModelsInfo(), so the token/keys/modelData/setModelData props
were dead; drop them from ModelDashboardProps (and the parent's now-unused
setModelData state) to sever the last of the shared-state coupling.

* test(ui): scope migration smoke's shell probe to the exact sidebar link

The migration smoke used a loose `locator("a", { hasText: "Virtual Keys" })`
to assert the dashboard shell rendered. The Models + Endpoints page content
itself links to the "Virtual Keys page", so on that route the substring filter
matched two anchors and tripped Playwright strict mode. Match the sidebar link
by its exact accessible name instead, which resolves to just the nav item.

* refactor(ui): remove orphaned pass-through-settings route (#30692)

The `page == "pass-through-settings"` arm in (dashboard)/page.tsx is
unreachable: it isn't a sidebar item and nothing in the app sets
?page=pass-through-settings. The Pass-Through Endpoints UI lives as a tab
inside the Models + Endpoints view (ModelsAndEndpointsView renders
PassThroughSettings), so the standalone switch arm is dead code. Remove it,
its now-unused import, and the matching enum member in the e2e pages fixture.

* fix(cost): stop non-string response service_tier from dropping cost tracking (#30706)

completion_cost extracted service_tier from the response object and the usage
object without an isinstance guard, so a non-string value (e.g. a dict) flowed
straight into _get_service_tier_cost_key and raised AttributeError on
service_tier.lower(). completion_cost re-raises, so the request's cost was lost.

PR #30690 fixed only the request-level optional_params path. This extends the
same guard to the response and usage paths by normalizing each extracted value:
a non-string tier (and the routing-only "auto" sentinel) is not billable, so it
coerces to None and pricing defers to the next concrete tier the provider served,
falling back to standard pricing when none is present.

Adds two regression tests driving a dict service_tier through completion_cost,
one on the response object (defers to the served usage tier) and one on the usage
object (prices at standard); both raise AttributeError before the fix.

* feat(agent-shin): automated PR/issue triage, low-quality auto-close, and review-gate label lifecycle (#30433)

* feat(triage): auto-close stale PRs with Greptile score <4/5

Adds .github/scripts/close_low_quality_prs.py and a daily workflow that
closes PRs which:
  - are open for at least 7 days, and
  - carry a most-recent greptile-apps review with Confidence Score <4/5,
  - and are not drafts or opt-out-labeled ('do not close', 'wip', etc.).

Each closure posts an explanatory comment telling the contributor how to
bring the PR back (rebase, re-request greptile, reopen at 4+/5). The
4/5 bar is already documented in the PR template
(.github/pull_request_template.md), so this just enforces it.

Tested with a dry run against the live BerriAI/litellm backlog of 1000
open PRs: 100 candidates identified, 598 PRs pass the bar (4+/5), 186
are too young, 97 are drafts, 19 lack any Greptile review and are left
alone.

Workflow defaults to closing 25 PRs/run as a safety net and supports
workflow_dispatch with overrides (close=false for a dry run, custom
min_age_days/min_score/limit).

18 unit tests cover score extraction (HTML/markdown/plain text, login
variants, multi-review picks latest) and per-PR evaluation (drafts,
opt-out labels, age, missing/passing/failing scores).

Co-authored-by: Mateo Wang <[email protected]>

* docs(templates): require expected/actual + QA proof for external contributions

PR template:
- Make the rubric explicit at the top: link an issue, OR provide a clear
  problem description + expected vs. actual + visual QA proof.
- Add dedicated sections for each piece so the bot has a deterministic
  shape to read.
- Keep the existing 'Linear ticket' section for internal contributors
  (they're exempt from the auto-triage rubric).

Bug report template:
- Split 'What happened?' into 'Actual behavior' + 'Expected behavior'.
- Make logs/screenshot a required textarea.
- Warning banner at the top tells external contributors that incomplete
  reports will be auto-closed (with re-evaluation on reopen).

Feature request template:
- Require a concrete use case + example in the motivation field, not just
  a one-liner pitch.
- Same auto-triage warning banner.

Co-authored-by: Mateo Wang <[email protected]>

* feat(triage): Agent Shin LLM-as-judge for external PRs and issues

Adds a new triage flow that evaluates external pull requests and issues
against the project's contribution rubric and, when configured to do so,
auto-closes non-conforming ones with an explanatory comment. Contributors
can update + reopen to be re-evaluated.

Scope:
- Internal BerriAI contributors (author_association OWNER/MEMBER/COLLABORATOR)
  and bot accounts are skipped entirely.
- 'Fixes #1234' / 'Resolves https://github.com/.../issues/N' in the PR body
  short-circuits to PASS without burning LLM tokens.
- LLM judge returns structured JSON (verdict, missing[], explanation);
  parser tolerates markdown fences and embedded JSON.
- LLM errors NEVER close PRs/issues — failure surfaces as 'skip-llm-error'.

Safety:
- pull_request_target / issues triggers are FORCED dry-run in the workflow;
  only manual workflow_dispatch with close=true (and AGENT_SHIN_ENABLED=true)
  takes destructive action.
- Default mode writes verdicts to GITHUB_STEP_SUMMARY only — no public
  comments until the team flips the AGENT_SHIN_ENABLED repo variable.
- LLM uses an OpenAI-compatible endpoint (model and base URL configurable
  via repo variables; key via OPENAI_API_KEY secret).

Files:
- .github/scripts/triage_with_llm.py   - judge orchestrator + CLI
- .github/workflows/triage_pr_with_llm.yml
- .github/workflows/triage_issue_with_llm.yml
- tests/test_litellm/test_github_triage_with_llm.py - 33 unit tests

End-to-end validated against four real PRs (#28117 internal collaborator,
#28108 bot, #28129 'Fixes #28128', #28116 no linked issue) and issue
#28132 with a stubbed LLM judge: each path produces the expected action.

Co-authored-by: Mateo Wang <[email protected]>

* feat(triage): scope Greptile auto-closer to external contributors + dry-run by default

- close_low_quality_prs.py now filters by GitHub author_association via
  the REST API: PRs from OWNER / MEMBER / COLLABORATOR (and bot accounts)
  are skipped with a new 'skip-internal' summary bucket.
- close_low_quality_prs.yml now defaults workflow_dispatch close=false,
  and ignores 'close=true' unless the new repo variable
  AGENT_SHIN_ENABLED is set to 'true'. Scheduled runs are dry-run only
  until the team flips that switch.
- Updated unit tests: one new test asserting internal authors are
  skipped, and an autouse fixture treats unspecified test PRs as
  external so the rest of the suite still exercises the close path.

Co-authored-by: Mateo Wang <[email protected]>

* fix(workflows): scheduled cron closes PRs; safe --close strip in triage

Co-authored-by: Yassin Kortam <[email protected]>

* fix(triage): scheduled cron stays dry-run; dedent prompts before interpolation

- close_low_quality_prs.yml: only workflow_dispatch with close=true (and
  AGENT_SHIN_ENABLED=true) actually closes PRs. Scheduled runs are always
  dry-run, matching the safety invariant documented for triage_pr/issue.
- triage_with_llm.py: textwrap.dedent on an f-string with multi-line
  interpolated bodies fails because the body's 2nd+ lines start at column 0,
  making the common-indent zero. Dedent the static template first, then
  .format() the title/body in.

Co-authored-by: Yassin Kortam <[email protected]>

* Fix bugs in auto-close PR triage scripts

- close_low_quality_prs.py: Treat author_association API lookup failures
  as internal (fail-safe) so transient errors don't cause internal
  contributors' PRs to be auto-closed.
- triage_with_llm.py: Update summary heading from 'Would post comment:'
  to 'Posted comment:' since this branch only runs after the comment
  has already been posted.

Co-authored-by: Yassin Kortam <[email protected]>

* feat(triage): default Agent Shin to gpt-5.4-mini with reasoning_effort=none

- Bump DEFAULT_MODEL from gpt-4o-mini to gpt-5.4-mini (more modern;
  4M total context window per OpenAI catalog, JSON-schema response
  format, function calling all supported).
- For gpt-5.x family models, pass reasoning_effort="none" via
  extra_body. gpt-5.x rejects temperature != 1 unless reasoning_effort
  is explicitly "none"; setting it lets us keep temperature=0 for
  deterministic JSON rubric judgments. extra_body works across openai
  SDK versions regardless of whether they natively type the kwarg.
- For non-gpt5 overrides (TRIAGE_MODEL=gpt-4o-mini etc.), reasoning_effort
  is not sent.
- 4 new unit tests cover: gpt-5.4-mini -> reasoning_effort=none,
  capitalized/dated gpt-5 variants -> reasoning_effort=none,
  gpt-4o-mini -> no extra_body, base_url passthrough.

Co-authored-by: Mateo Wang <[email protected]>

* fix(triage): bugbot — drop dead gh_json and fix --optout-label append-with-default

- Removed the unused gh_json helper (bugbot low-severity dead code).
- Replaced argparse `action="append", default=[...]` with default=None
  + DEFAULT_OPTOUT_LABELS fallback. The mutable-default + append combo
  silently APPENDS to the canonical defaults instead of replacing them,
  so --optout-label could not actually scope the opt-out list.
- Added tests covering both the canonical default and the
  flag-replaces-defaults behavior.

Co-authored-by: Mateo Wang <[email protected]>

* fix(triage): bugbot — tighten linked-issue regex, fail-safe author_association, fix empty TRIAGE_MODEL

Three independent bugbot findings against triage_with_llm.py:

1. LINKED_ISSUE_PATTERN included weak keywords (`see`, `ref`,
   `addresses`) so casual mentions like "See #1234 for context" were
   short-circuited to pass-linked-issue without ever calling the LLM —
   contradicting the prompt's own "a bare issue number without a closing
   keyword counts only if it's clearly the related issue (not a passing
   mention)" rubric. Limit the regex to GitHub's documented PR-closing
   keywords (fixes/fix/fixed/closes/close/closed/resolves/resolve/resolved).

2. is_internal_contributor() treated an empty/missing author_association
   as external (eligible for the destructive close path), while the sibling
   is_external_pr_author() in close_low_quality_prs.py fail-safes the same
   case as internal. Align the two so a partial/unknown GitHub response can
   never make a PR eligible for auto-close.

3. argparse `default=os.environ.get("TRIAGE_MODEL", DEFAULT_MODEL)` returns
   the empty string when GitHub Actions exposes an unset repo variable as
   an empty-string env var (the optional vars.TRIAGE_MODEL case in the
   workflow). Use `os.environ.get(...) or DEFAULT_MODEL` so empty -> default,
   matching the existing OPENAI_BASE_URL pattern.

Tests:
- Casual mentions now must fall through to the LLM (parametrized);
  added an orchestration test ensuring "See #1234" reaches the judge.
- Empty/missing author_association now fails safe (parametrized).
- Empty TRIAGE_MODEL env var falls back to DEFAULT_MODEL; explicit
  TRIAGE_MODEL is still honored.

Co-authored-by: Mateo Wang <[email protected]>

* fix(workflows): bugbot — gate Agent Shin --close on '= true' not '!= false'

The PR and issue Agent Shin workflows gated the destructive --close
flag with [ "${DISPATCH_CLOSE:-false}" != "false" ]. That pattern
treats anything other than the literal string "false" as enabling
closure — "True", "yes", "1", typos, accidental whitespace, etc.
The workflow_dispatch input UI is a 'true'/'false' choice dropdown so
the form is constrained, but the API (`gh workflow run -f close=...`)
accepts any string, and a CI cron / external invoker passing a
non-canonical truthy value would have silently enabled real
contributor PR closures.

Mirror the sibling Greptile closer's [ "${CLOSE_FLAG}" = "true" ]
pattern: only the EXACT string "true" enables --close; every other
value (including the unset/empty default) resolves to dry-run. This is
the fail-safe philosophy applied everywhere else in this PR.

Added tests/test_litellm/test_github_triage_workflows.py with two
parametrized invariants:
  1. The destructive gate uses '= "true"' for its env-var
     comparison (either bare '${ENV}' or '${ENV:-false}' form
     accepted), and never the fail-open '!= "false"' pattern.
  2. Every destructive gate is also gated on AGENT_SHIN_ENABLED being
     "true" — either by entering the close branch on '=' or by
     bailing out early on '!=' — so flipping the repo variable off is
     a true kill switch regardless of per-run inputs.

Manually verified the test fails on the buggy '!= "false"' pattern and
passes on the fix, so it would have caught the regression at PR time.

Co-authored-by: Mateo Wang <[email protected]>

* feat(triage): close any PR (incl. drafts, any age); add @agent-shin reconsider flow

Follow-up to PR #28117. Three behavior changes + one new workflow,
addressing the team's concerns on the original review:

1) Apply auto-close to ALL open PRs, not just those over a week old.

   - close_low_quality_prs.py: --min-age-days default flipped from 7 to
     0. The flag is preserved as an opt-in safety net for one-off
     backfill runs that want to spare very-young PRs, but the daily
     scheduled sweep now closes external-author PRs as soon as Greptile
     scores them <4/5.
   - close_low_quality_prs.yml: workflow_dispatch input default also
     flipped to 0; doc comments updated.

2) Apply auto-close to draft PRs too.

   - close_low_quality_prs.py: removed the skip-draft branch in
     evaluate_pr. Drafts are NOT a free pass — the team's intent is
     'open PR count == PRs internal collaborators need to action on',
     so a draft Greptile scored 2/5 still belongs in the closed bucket.
     Authors who genuinely need a long-lived draft can attach the 'wip'
     opt-out label, which is unchanged.
   - The 'skip-draft' action is gone; the 'wip' label still skips.

3) Address the 'OSS contributors cannot reopen a bot-closed PR' wrinkle.

   GitHub does NOT let an external (non-write-access) contributor
   reopen a PR that was closed by a bot or maintainer (long-standing
   limitation). The original PR's close-comments told contributors to
   'Reopen the PR — I'll re-evaluate automatically', which is broken
   for the very audience this triage targets. Two changes:

   a) Reword every close-comment (Greptile sweep + Agent Shin PR
      close + Agent Shin issue close + PR template) to recommend:
        - Open a new PR with the updated branch (primary path).
        - Or comment '@agent-shin reconsider' on the closed PR for a
          re-evaluation that, on pass, reopens the PR via the bot's
          GH_TOKEN write access.

   b) Add the @agent-shin reconsider workflow:
        - .github/workflows/triage_reconsider.yml: new
          'issue_comment'-triggered workflow. Authorizes only the
          PR/issue author or an internal collaborator
          (OWNER/MEMBER/COLLABORATOR), gated via a step output so
          unauthorized commenters never reach the destructive steps.
          Globally gated on AGENT_SHIN_ENABLED='true' (positive form,
          matching the test_github_triage_workflows guardrail
          patterns).
        - triage_with_llm.py: --reconsider mode. On a closed PR/issue,
          re-runs the LLM judge (or linked-issue regex short-circuit)
          and:
            - on pass: reopens via reopen_pr/reopen_issue + posts a
              'Re-evaluated and reopened' comment.
            - on fail: leaves closed and posts a 'still missing X'
              comment so the contributor can iterate again.
          Reconsider-on-open is a no-op ('skip-not-closed').
          Internal-author + bot-account skips still take priority over
          reconsider.

4) Greptile-on-closed-PRs question: the team asked whether Greptile can
   re-review a closed PR. Greptile's docs don't address this and we
   shouldn't promise behavior we can't verify, so the new close-comment
   wording does NOT instruct contributors to 're-request greptile on
   the closed PR'. Instead it points them at the new-PR path (which
   Greptile definitely reviews) or the @agent-shin reconsider trigger
   (which re-runs the LiteLLM-side rubric judge, not Greptile).

Tests: 93 passing (was 59).

  - test_github_close_low_quality_prs.py: replaced 'skip drafts' test
    with 'closes drafts when score is low' + 'closes brand-new PR when
    min_age=0' + 'no skip when min_age=0'. The 'skip too young'
    assertion is preserved as opt-in.
  - test_github_triage_with_llm.py: 6 new TestTriageOrchestration cases
    for reconsider mode (skip-not-closed on open, reopen on pass,
    still-failing comment on fail, linked-issue short-circuit reopen,
    skip internal author in reconsider, reopen-issue on pass) + a new
    TestCloseCommentText class that pins the user-facing 'open a new
    PR' + '@agent-shin reconsider' wording.
  - test_github_triage_workflows.py: added triage_reconsider.yml to
    the destructive-gate guardrail table; AGENT_SHIN_ENABLED is its
    own destructive gate (no separate per-run flag needed).

Co-authored-by: Mateo Wang <[email protected]>

* test(triage): pin safe behavior for curly braces in PR/issue title+body

Adds regression tests covering the bugbot high-severity finding that
str.format() would crash on user-supplied content containing { or }.
Empirically str.format() does NOT re-parse interpolated values — only
the template literal is scanned for replacement fields — so the bug
does not exist in the current code, but pinning the safe behavior
prevents a future templating change from silently reintroducing it.

Also pins the dedented prompt shape (no leading 8-space indentation on
template lines) so a future change to the build_*_prompt functions can't
silently regress the LLM judge prompt format on multi-line bodies.

Co-authored-by: Mateo Wang <[email protected]>

* fix(triage): bugbot — reconsider dry-run + bot-closed guard + rate limit

Address three Greptile/veria-ai concerns on the @agent-shin reconsider
flow:

1. **Reconsider had no dry-run path.** The previous reconsider mode
   ignored `--close` and always posted comments + reopened on a pass.
   A local operator running
   `python triage_with_llm.py --reconsider --pr N` would silently
   take destructive GitHub actions with no way to preview. Reconsider
   now honors `close=False` the same way regular triage does and
   returns `would-reopen` / `would-reconsider-still-failing` for
   step-summary rendering.

2. **Reconsider could reopen maintainer-closed PRs/issues** (Medium
   security finding from veria-ai). The workflow only checked that the
   commenter was authorized — it did NOT check that the most recent
   close was performed by Agent Shin. A contributor could comment
   `@agent-shin reconsider` on a PR a maintainer closed for non-rubric
   reasons (duplicate, security report, design rejection) and have the
   bot reopen it. Add `was_closed_by_agent_shin()` which inspects the
   issue events API for the most recent `closed` actor and only
   permits reopen when that actor matches the configured bot login
   (default `github-actions[bot]`, overridable via env). Fail-closed
   on missing events.

3. **No rate-limiting on the reconsider trigger.** Every
   `@agent-shin reconsider` comment burns CI minutes + an OpenAI API
   call. Add a 10-minute cooldown via
   `seconds_since_last_reconsider_verdict()` which greps the issue's
   comment list for the bot's own verdict marker
   (`<!-- agent-shin:reconsider-verdict -->`). Inside the window the
   triage returns `skip-rate-limited` and the LLM never runs.

Workflow update:
- `triage_reconsider.yml` now passes `--close` only when
  `AGENT_SHIN_ENABLED=true`, matching the pattern of
  `triage_pr_with_llm.yml`. The script runs in both states so the
  verdict still appears in the step summary for QA.

Tests:
- Add 5 reconsider safety tests: dry-run for pass / fail / linked-issue
  short-circuit, bot-closed-guard refusal on maintainer close,
  rate-limit refusal inside the cooldown window, and cooldown-elapsed
  acceptance.
- Add unit tests for `was_closed_by_agent_shin` (bot / maintainer /
  missing actor / env-override) and
  `seconds_since_last_reconsider_verdict` (no marker / multiple
  markers / non-bot comment with marker / bot comment without marker).
- Pin the `<!-- agent-shin:reconsider-verdict -->` marker in both
  reopen and still-failing comments — dropping it would silently
  break the cooldown.

Existing reconsider tests updated to pass `close=True` (the
production path now) + stub the new guards via
`_stub_reconsider_guards`. 112 tests pass (was 93).

Co-authored-by: Mateo Wang <[email protected]>

* feat(triage): 1-day grace period before close + SwiftWinds immediate-close bypass

- Add a 24-hour grace window between the first low-quality detection
  and the actual auto-close. The first detection posts a warning
  comment that explicitly says "You have 1 day to address this before
  this PR is auto-closed" and points the contributor at:
    * `@agent-shin reconsider` to request another look (and re-open)
    * `@greptileai` to request a fresh Greptile review — works
      even after the PR is closed
- Both `triage_with_llm.py` (LLM judge) and `close_low_quality_prs.py`
  (Greptile-score closer) share the same `<!-- agent-shin:grace-warning -->`
  HTML marker so a warning posted by either path is recognized by both.
- Add IMMEDIATE_CLOSE_LOGINS = {swiftwinds} to bypass BOTH the grace
  period AND the dry-run / AGENT_SHIN_ENABLED gating. SwiftWinds is the
  user's personal account (no push permissions to litellm) used to
  dogfood the bot; user explicitly asked: "For SwiftWinds, just close
  immediately. Faster iteration that way."
- Update the standard close comments to mention that `@greptileai`
  works even after the PR is closed.
- Add 23 new tests covering: warn-grace on first detection, skip during
  grace window, close after grace expires, SwiftWinds bypass (case
  insensitive, with close=False, no random-login false positives), the
  grace-warning text invariants, and the SwiftWinds entry in the
  IMMEDIATE_CLOSE_LOGINS constant.

Co-authored-by: Mateo Wang <[email protected]>

* fix: skip grace-period text in close comment for IMMEDIATE_CLOSE_LOGINS

For PRs from IMMEDIATE_CLOSE_LOGINS (e.g. swiftwinds), evaluate_pr
returns 'close' immediately without ever posting a grace warning, so
the close comment should not reference a 1-day grace period.

Make close_pr take a grace_period_elapsed flag, default True, and
pass False from the main loop when the close path was the
immediate-close branch.

Co-authored-by: Yassin Kortam <[email protected]>

* fix(close-low-quality-prs): report actual closes in dry-run summary

IMMEDIATE_CLOSE_LOGINS PRs are closed even when the global --close flag is
not set, but the summary used the global dry-run flag to choose between
'would close' and 'closed'. Split the count so operators can see both
actual closures and dry-run would-be closures.

Co-authored-by: Yassin Kortam <[email protected]>

* chore(triage): vendor Agent Shin (#28117) onto demo branch

Brings the Agent Shin OSS-triage scripts, workflows, issue/PR templates, and
tests from PR #28117 onto this branch so the new review-gate feature and its
end-to-end demo are self-contained and runnable in CI.

https://claude.ai/code/session_01XyyWa8t2VYmoGd6mKMEqkZ

* feat(triage): add "ready for review" label lifecycle to Agent Shin

Adds review_gate(), a state machine that keeps a `ready for review` label in
sync with whether an external PR clears BOTH gates — the LLM rubric and
Greptile's most recent confidence score:

- pass (untagged)            -> add label + "ready for review" / "all clear" comment
- pass (already tagged)      -> no-op (idempotent across re-runs)
- regress (Greptile < 4/5 or QA proof removed) -> remove label + "what's missing"
  comment, PR stays open
- recover after a regression -> "all clear again" comment + re-add the label
- fail & untagged, < 24h old -> one-time "what's missing" notice (grace window)
- fail & untagged, > 24h old -> close + comment (reopen via @agent-shin reconsider)

The label itself is the persisted state, so comments fire only on transitions
(never on every scheduled run). All side effects are gated behind --close, so
the dry-run contract matches the existing triage flow. Lifecycle comments use
hidden HTML markers and deliberately avoid the auto-close marker so they never
trip the reconsider provenance check.

Relocates the shared Greptile helpers (extract_greptile_score, SCORE_PATTERN,
GREPTILE_BOT_LOGINS, parse_iso8601) into triage_with_llm.py so the daily sweep
and the review gate read the score through one implementation, and adds the
review_gate.yml workflow (dry-run unless AGENT_SHIN_ENABLED=true) plus 18 unit
tests covering every branch and a full pass->regress->recover cycle.

https://claude.ai/code/session_01XyyWa8t2VYmoGd6mKMEqkZ

* Port review-gate feature from #28758 onto #28147 triage scripts

Adds the "ready for review" label lifecycle (originally PR #28758) on top
of #28147's refactored triage_with_llm.py. The original commit was
authored against an older snapshot of #28117 and could not be applied
cleanly, so the additions were re-applied surgically:

- New constants: READY_FOR_REVIEW_LABEL, DEFAULT_GRACE_DAYS,
  DEFAULT_MIN_GREPTILE_SCORE, READY/REGRESSED/WITHIN_GRACE markers,
  GREPTILE_BOT_LOGINS, SCORE_PATTERN, AGENT_SHIN_AUTO_CLOSE_MARKER.
- New helpers: add_label, remove_label, extract_greptile_score,
  parse_iso8601 (the latter two mirrored from close_low_quality_prs.py
  so the daily sweep and the review gate read the score through the
  same logic).
- New comment formatters: format_ready_for_review_comment,
  format_all_clear_comment, format_regression_comment,
  format_within_grace_comment.
- New entry point: review_gate() implementing the pass/regress/recover
  state machine, with the label itself acting as persisted state so
  transition comments fire only on actual transitions.
- main() learns --review-gate, --grace-days, --min-greptile-score and
  dispatches to review_gate() when the flag is set.

Verified via tests/test_litellm/test_github_review_gate.py (18 tests)
and the existing triage suites (144 more) — all 162 pass.

Co-Authored-By: Claude Opus 4.7 <[email protected]>

* agent_shin: extract shared constants/helpers; cover review_gate.yml in guardrail tests

Bug 1: `triage_with_llm.py` and `close_low_quality_prs.py` each defined
their own copies of `extract_greptile_score`, `parse_iso8601`,
`GREPTILE_BOT_LOGINS`, `SCORE_PATTERN`, `GRACE_COMMENT_MARKER`,
`GRACE_PERIOD_SECONDS`, `IMMEDIATE_CLOSE_LOGINS`, and
`AGENT_SHIN_DEFAULT_BOT_LOGIN`. The comments explicitly said the two
copies had to stay in sync, but nothing enforced it. A future change to
one (e.g. extending `SCORE_PATTERN` for a new Greptile output format)
would silently diverge from the other and the daily sweep and the LLM
judge would disagree on which PRs have low scores.

Extract these to `.github/scripts/agent_shin_shared.py` and re-export
them from each script so the existing test attribute access
(`triage_module.GRACE_COMMENT_MARKER`, etc.) keeps working without
any test changes.

Bug 2: `review_gate.yml` is a destructive workflow (close PRs, add/remove
labels, post comments) with the same gating philosophy as the others
(`AGENT_SHIN_ENABLED = "true"` + a per-run `CLOSE_FLAG = "true"`),
but it was missing from `DESTRUCTIVE_GATE_ENV` in the guardrail tests.
Add it so a future regression (e.g. flipping to `!= "false"`) is
caught by the same parameterized invariants as every other workflow.

Co-authored-by: Yassin Kortam <[email protected]>

* agent_shin: fix bug bundle (gated LLM key, author-filtered marker dedup, dedup gh/grace helpers)

Co-authored-by: Yassin Kortam <[email protected]>

* agent_shin: fix review_gate close-after-regression and case-insensitive label match

Co-authored-by: Yassin Kortam <[email protected]>

* feat(triage): add one-shot 7-day heads-up sweep for Agent Shin rollout

Adds a rollout-day workflow that comments on every open external PR/issue
that the new triage bot WOULD auto-close, giving contributors 7 days to
fix their description before any destructive action runs.

Why now: merging this PR enables Agent Shin in dry-run. The follow-up
"enact" PR (next Monday) flips the destructive paths on. Without this
heads-up, contributors would get a close-comment on day 8 with no prior
warning. The heads-up names the cutoff date, lists the rubric, calls out
each PR/issue's specific missing pieces, and explains the recovery paths
(@agent-shin reconsider for PRs, edit + reopen for issues).

Files
- .github/scripts/_agent_shin_actions.py — thin maybe_post_comment /
  maybe_close_* / maybe_add_label / etc. wrappers. Each is a single
  `if dry_run: log; return; else: call_through()` so a dry-run preview
  differs from the real run in exactly one call site per mutation. The
  call-through goes via `triage_with_llm.<name>` (module-qualified) so
  monkeypatching the underlying function in tests is reflected here.
- .github/scripts/triage_rollout_heads_up.py — the sweep. Iterates every
  open PR + issue via `gh pr list` / `gh issue list`, runs the future
  rubric (review_gate for PRs, triage(kind="issue") for issues), and
  posts the heads-up on any item that would be auto-closed. Idempotent
  via a `<!-- agent-shin:rollout-heads-up -->` marker. Defaults to dry-
  run; --close opts in to real posts. --close-on overrides the cutoff
  date (defaults to today + 7 days).
- .github/workflows/triage_rollout_heads_up.yml — one-shot workflow.
  Triggers on push to litellm_internal_staging filtered to the script
  path (fires on rollout merge) plus workflow_dispatch with a dry_run
  input that defaults to "true" for safe manual re-runs.
- tests/test_litellm/test_triage_rollout_heads_up.py — 28 unit tests
  covering: the dry-run wrappers (each maybe_* gates correctly), the
  _would_be_closed predicate for PR vs. issue results, the comment
  formatter (cutoff/rubric/marker/recovery wording), per-item dispatch
  (skip-not-open, skip-internal-author, skip-already-notified,
  skip-passing, would-post/posted), and the sweep loop end-to-end.

Local preview (no GitHub mutations):
    python3 .github/scripts/triage_rollout_heads_up.py --repo BerriAI/litellm

Real run (what the workflow does):
    python3 .github/scripts/triage_rollout_heads_up.py --repo BerriAI/litellm --close

TODO: replace the placeholder ROLLOUT_BLOG_URL with the canonical
docs URL once the litellm-docs PR ships.

Co-Authored-By: Claude Opus 4.7 <[email protected]>

* fix: gate reconsider workflow OPENAI_API_KEY + remove dead actions wrappers

- Mirror sibling Agent Shin workflows by only exposing OPENAI_API_KEY in
  triage_reconsider.yml when vars.AGENT_SHIN_ENABLED == 'true'. Previously
  the secret was unconditionally exposed, so any PR/issue author could
  trigger paid LLM calls by commenting '@agent-shin reconsider' even while
  the bot was supposed to be in dry-run.
- Remove the six unused dry-run wrappers (maybe_close_pr, maybe_close_issue,
  maybe_reopen_pr, maybe_reopen_issue, maybe_add_label, maybe_remove_label)
  from _agent_shin_actions.py — only maybe_post_comment is used by rollout
  scripts. Drop the associated tests that exercised the now-removed
  functions.

Co-authored-by: Yassin Kortam <[email protected]>

* fix: address triage script edge cases

- triage_rollout_heads_up.py: replace %-d strftime specifier (GNU-only)
  with portable day formatting so the script doesn't crash on Windows.
- close_low_quality_prs.py: skip malformed JSON lines in fetch_pr_comments
  instead of letting one bad line abort the daily sweep, matching the
  pattern in triage_with_llm._iter_paginated_json.
- triage_with_llm.py: move has_linked_issue short-circuit before
  build_pr_prompt to avoid unnecessary prompt construction on PRs that
  link an issue.

Co-authored-by: Yassin Kortam <[email protected]>

* fix(scripts): per-PR error isolation and limit grace warnings in close_low_quality_prs

- Wrap per-PR processing in try/except so a transient GitHub API failure
  on one PR no longer aborts the entire daily sweep (mirrors the pattern
  already used in triage_rollout_heads_up.py).
- Have --limit bound *all* destructive write actions (closures and grace
  warnings combined), not just closures. Prevents a backlog of newly
  failing PRs from flooding contributors with comments in a single run.

Co-authored-by: Yassin Kortam <[email protected]>

* fix(agent-shin): remove 1000-PR cap on bulk sweeps; sweep entire backlog

Both bulk-sweep scripts hardcoded `gh {pr,issue} list --limit 1000`, and gh
lists newest-first — so the OLDEST ~900 PRs and ~380 issues were silently
dropped. That's exactly the stale backlog the daily closer and one-shot
rollout heads-up exist to catch.

Extract a single `list_open_items(kind, *, repo, fields)` helper into
`agent_shin_shared.py` with `GH_LIST_ALL_LIMIT = 100_000` — a ceiling far
above any realistic open backlog so gh paginates until the queue is
exhausted. `fetch_open_prs` and `_list_open_numbers` both delegate to it,
so the limit lives in exactly one place going forward.

Verified live against BerriAI/litellm:
- `fetch_open_prs` -> 1981 PRs (was 1000)
- `_list_open_numbers(issue)` -> 1382 issues (was 1000)
- `_list_open_numbers(pr)` -> 1981 PRs (was 1000)

Adds 7 regression tests asserting the new limit is passed, the dedicated
`gh {pr,issue} list` command + fields are used per kind, bad kind raises
ValueError, and both callers delegate to the shared helper.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

* fix(agent-shin): require non-mocked end-to-end QA proof for PR pass

The PR rubric previously passed any PR with a linked issue, regardless
of whether it showed the fix actually working. Sample spot-check found
21/25 recent external PRs passing, including ones that linked an issue
but provided zero QA evidence.

Tighten the rubric so a pass now requires BOTH:

  (1) CONTEXT — a linked issue OR a clear problem description with
      expected-vs-actual behavior.
  (2) END-TO-END QA PROOF — at least one of:
      (a) screenshot(s) of the fix working,
      (b) screen recording / video,
      (c) specific commands actually run, paired with their real
          output, against the real system.

Mocked unit tests, generic 'I tested it' claims, 'all tests pass'
without output, and the linked issue itself are explicitly excluded
from QA proof.

Also add 'qa_proof_type' to the JSON schema so the per-PR report
surfaces which kind of proof (or 'none') the judge saw.

Re-sample on the same 25 recent external PRs shifts the verdict
distribution from 21 pass / 4 fail to 4 pass / 21 fail, with zero
prior-fails now passing — the stricter rule catches PRs that ship
only with unit-test claims and no real integration evidence.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

* feat(agent-shin): link blog explainer from every action-required bot comment

Adds "What's this and why am I getting it?" links to docs.litellm.ai/blog/
agent-shin-triage from the four comments contributors actually read when
something went wrong: PR close, PR grace warning, issue close, issue grace
warning. PR comments also link the rubric section directly from the
QA-proof bullet so contributors can self-serve "what counts as proof"
without pinging a maintainer.

Pins the new guarantees in tests: blog link must appear in all four
comments, and the PR close comment must continue to flag mocked-dependency
unit tests as insufficient proof.

The linked blog post is in BerriAI/litellm-docs PR #240; the URL will 404
until that lands.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

* fix(review_gate): raise sweep limit from 1000 to 100000 to match GH_LIST_ALL_LIMIT

gh lists newest-first, so capping at 1000 silently drops the oldest open
PRs — exactly the stale ones the daily sweep is meant to reconcile. Use
the same ceiling as agent_shin_shared.GH_LIST_ALL_LIMIT so the workflow
sees the entire backlog.

Co-authored-by: Yassin Kortam <[email protected]>

* Fix three Agent Shin triage edge cases

- review_gate: expire the regression-marker short-circuit after grace_days
  so PRs that were regressed and then abandoned can eventually be closed.
- review_gate: when the rubric short-circuits to pass via the linked-issue
  regex but Greptile drags the PR below the bar, replace the synthetic
  'LLM was not called' explanation with the real Greptile shortfall so
  regression / close comments are not misleading.
- triage_rollout_heads_up._comments_have_marker: drop the unused 'kind'
  parameter and filter by bot author so a contributor quoting the
  heads-up via 'Quote reply' cannot trick the idempotency check, matching
  the pattern in triage_with_llm._has_marker.

Co-authored-by: Yassin Kortam <[email protected]>

* fix: pass min_greptile_score through to ready-for-review comment text

Co-authored-by: Yassin Kortam <[email protected]>

* feat(agent-shin): warmer triage comments — bullet-train emoji, 'what you got right' section, softer 'park this for later' framing

User feedback on the auto-triage comments contributors will see:

1. Tone — the previous 'You have 1 day to address this before this PR is
   auto-closed' framing reads as an ultimatum. Replace with: 'If the
   description isn't updated in the next 1 day, I'll auto-close this PR.
   That's not us saying we don't care about the change — we want the
   open-PR list to mirror what a maintainer can act on right now, so
   contributors don't get lost in a backlog. A closed PR is a soft "park
   this for later," not a rejection. Take your time.'

2. Positive feedback — the previous comments only listed what was missing.
   Now every close + grace-warning comment opens with a 'What you got
   right:' section rendered from the judge's per-field flags. Contributors
   see a checkmark for everything they got right (linked issue, problem
   description, expected/actual, QA proof for PRs; runnable repro,
   screenshot/log, expected/actual, motivation+example for issues) before
   the gaps. The block is omitted entirely when nothing is present so
   we never render 'What you got right: (nothing).'

3. Reconsider trigger — the previous grace warning told contributors to
   comment '@agent-shin reconsider' during the grace window. They don't
   need to — the bot re-checks on every sweep. The new copy says 'just
   update the description, no need to ping me' for the grace path, and
   reserves '@agent-shin reconsider' for the post-close recovery path.

4. Bullet-train emoji — replace 👋 with 🚄 (Shinkansen, the symbol of
   Agent Shin) across every action-required comment: PR close, PR grace
   warning, issue close, issue grace warning, within-grace, Greptile-
   closer grace warning, rollout heads-up. Pinned in tests so a future
   refactor can't silently revert.

5. Greptile-post-close — the @greptileai bullet now explicitly says 'a
   low Greptile score isn't a blocker either,' since the previous copy
   buried the fact that @greptileai works after auto-close.

Comment templates updated: format_pr_close_comment,
format_issue_close_comment, format_grace_warning_pr_comment,
format_grace_warning_issue_comment, format_within_grace_comment
(triage_with_llm.py); format_grace_warning_comment
(close_low_quality_prs.py); format_heads_up_comment header
(triage_rollout_heads_up.py).

New helpers: _format_present_for_pr / _format_present_for_issue /
_format_present_block, driven off the existing per-field flags the
LLM judge already emits — no prompt change needed.

New tests pin: bullet-train emoji in every action-required comment;
'What you got right' appears with ✅ bullets when fields are present;
the block is omitted when no fields are present; 'park this for
later' / 'not a rejection' softer framing; grace warnings tell the
contributor 'no need to ping' during the grace window (reconsider is
the post-close path only).

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

* feat(agent-shin): gate triage on a dogfood allowlist

Add ALLOWLIST_LOGINS to agent_shin_shared so Agent Shin only acts on the
named accounts while the set is non-empty. mateo-berri and SwiftWinds are
allowlisted for the dogfood rollout; everyone else is skipped with
skip-not-allowlisted across all four entrypoints (triage, review gate, the
daily low-quality sweep, and the rollout heads-up).

For an allowlisted author the usual internal/external classification is
bypassed, so a maintainer's own org account still gets triaged during
testing. Emptying the set lifts the restriction and restores full triage
for the public rollout. The gate is dependency-injected via an `allowlist`
parameter defaulting to the constant, so the internal/external-skip paths
stay testable.

* feat(agent-shin): tighten QA-proof and issue rubrics, ack reconsider with reactions

Reorder the end-to-end QA proof options to video, then screenshots, then
exact commands with their real output across the PR template, the LLM judge
prompts, and every contributor-facing comment, and spell out that mocked or
stubbed runs (including pytest on the repo's own unit tests, which mock the
provider, DB, and network) never count as proof. QA proof is now required of
all contributors, not just external ones.

Tighten the issue bug-report rubric to require end-to-end evidence of the bug
(the "before" half: a video, screenshot, or command paired with real output)
plus expected vs. actual behavior, drop the bias toward PASS, and collapse the
separate has_repro/has_proof flags into a single has_repro signal.

Standardize the bullet-train emoji and strip em dashes from the bot's
public-facing messages, and route issue recovery through @agent-shin
reconsider since GitHub doesn't let OSS authors reopen an issue a bot closed.

Acknowledge an @agent-shin reconsider the moment it's accepted with an eyes
reaction and a thumbs-up once the run finishes, both gated on
AGENT_SHIN_ENABLED so dry-run leaves no trace.

* fix(agent-shin): shorten auto-close grace to 2 hours and drop the instant-close bypass

Two dogfooding changes to the Agent Shin grace window. First, the warn-then-close
grace (GRACE_PERIOD_SECONDS) drops from a day to 2 hours so the "fix it before it
closes" loop can be exercised in one sitting; the constant carries a note to bump
it back up for the public rollout.

Second, remove IMMEDIATE_CLOSE_LOGINS entirely. SwiftWinds (the external dogfood
account) used to skip the grace window and close on first detection, which also
meant closing real PRs even during a scheduled dry run because the per-PR
override flipped dry_run off. It now follows the same warn-then-close path as
every other author, so a low-quality PR is warned first and only closed once the
2-hour window elapses. This also closes the Greptile finding that the sweep could
mutate real PRs while AGENT_SHIN_ENABLED was still off.

The review gate's separate age-based grace (DEFAULT_GRACE_DAYS) is left unchanged.

Regression tests pin that SwiftWinds now warns-grace instead of closing instantly,
and that a dry-run sweep over a closeable PR reports "would close" without making
any GitHub mutation.

* fix(agent-shin): gate reconsider reopen on an Agent Shin close marker

was_closed_by_agent_shin only checked that the most recent close actor was
the bot identity. That identity defaults to github-actions[bot], which is
shared by every workflow in the repo (stale/duplicate sweeps included), so a
contributor could @agent-shin reconsider an item another workflow closed and,
if the description passed the rubric, get it reopened even though Agent Shin
was never the closer.

Require a second, Agent-Shin-specific signal alongside the actor check: an
auto-close comment stamped with a hidden AGENT_SHIN_CLOSE_MARKER. Both close
paths (the grace-period close and the review-gate close) flow through
format_pr_close_comment / format_issue_close_comment, so stamping the marker
there covers every real close while leaving the grace warnings unmarked. The
guard stays fail-closed: no marker, no reopen.

This also replaces the unused AGENT_SHIN_AUTO_CLOSE_MARKER constant (a visible
phrase the guard never consulted) with the hidden marker the guard now relies
on.

* fix(agent-shin): stamp close marker on sweep closes and disclose regression deadline

The daily Greptile sweep's close comment advertised `@agent-shin reconsider`
but never stamped AGENT_SHIN_CLOSE_MARKER, so the reconsider reopen guard
(was_closed_by_agent_shin), which now also requires that marker, silently
rejected every sweep-closed PR with `skip-not-bot-closed`. Move the marker into
agent_shin_shared so both close paths share one source of truth, extract
format_close_comment so the sweep close comment is unit-testable, and stamp the
marker there.

Also disclose the grace_days deadline in the review-gate regression comment; it
promised "the PR stays open" without mentioning that a still-failing PR is
auto-closed grace_days after the notice, which would surprise contributors with
a close they were never warned about.

* fix(triage): tighten Agent Shin reconsider reopen guards

The bot-closed guard accepted any historical Agent Shin marker comment
on the thread as proof that Agent Shin owned the latest close, so a
post-reopen close by another workflow under the shared
`github-actions[bot]` identity could still satisfy the gate and let
`@agent-shin reconsider` reopen a PR that Agent Shin did not close
this cycle. `fetch_last_close_event` now also returns the latest
`closed` event timestamp, and `was_closed_by_agent_shin` requires
the most recent Agent Shin marker comment to sit at (or just before)
that timestamp, with a small skew window for clock drift between the
events and comments APIs.

In the same path the LLM verdict check used `decision != "fail"` to
choose the reopen branch, which treated a missing, empty, or typo
verdict as a pass. Reopen is destructive, so the check now requires an
explicit `decision == "pass"` and ambiguous verdicts fall through
to the "still failing" branch instead.

* style(agent-shin): black-format reconsider guard hardening

* docs(agent-shin): scope dry-run wrapper docstring to the single existing helper

The module docstring claimed it wrapped every Agent Shin mutation and
referenced post_comment/close_pr/etc., but only maybe_post_comment exists.
Describe the single helper accurately while keeping the dry-run pattern
guidance for any future wrapper.

* chore(agent-shin): defer issue/PR template changes to the rollout PR

The triage and review-gate automation is gated to the allowlisted authors
(mateo-berri, SwiftWinds) and AGENT_SHIN_ENABLED, so during this rollout it
only acts on internal PRs/issues. The issue and PR templates have no such
gate; …
fzowl pushed a commit to fzowl/litellm that referenced this pull request Jun 24, 2026
…ck (BerriAI#30695)

Several CI jobs run the proxy against a model whose api_base is a shared
"fake OpenAI endpoint" hosted on Railway
(exampleopenaiendpoint-production.up.railway.app) so the E2E runs return
canned responses without paying for or depending on a live provider. When
that single deployment is down, every one of those jobs fails with
"404 Application not found" even though nothing in the PR is broken; the
whole repo is coupled to the uptime of one free external service.

This adds tests/_fake_openai_endpoint_server.py, a small canned-response
OpenAI-shaped server (chat, text, embeddings, streaming with usage, and the
"429" rate-limit special case), and a reusable start_fake_openai_endpoint
CircleCI command that runs it on host port 8190 and waits until healthy. The
affected jobs now inject FAKE_OPENAI_API_BASE pointing at the local server,
and the example configs they mount resolve api_base from that env var. The
intentionally bad fallback URL in proxy_server_config.yaml is left untouched
so the fallback test still exercises a failing upstream.

Wired into build_and_test, litellm_router_testing,
db_migration_disable_update_check, proxy_logging_guardrails_model_info_tests,
proxy_spend_accuracy_tests, proxy_multi_instance_tests,
proxy_store_model_in_db_tests, and proxy_build_from_pip_tests.
fzowl pushed a commit to fzowl/litellm that referenced this pull request Jun 24, 2026
…ndpoint (BerriAI#30900)

* test: point router/completion/triton tests at the local fake OpenAI endpoint

The shared Railway-hosted mock (exampleopenaiendpoint-production.up.railway.app)
takes down unrelated CI jobs whenever it is unreachable. BerriAI#30695 moved the mounted
proxy configs onto a job-local fake server but left these in-Python api_base
literals pointing at the dead host, so litellm_router_testing, local_testing_part1,
local_testing_part2 and llm_translation_testing still fail with a 404
"Application not found" when Railway is down

Resolve the api_base from FAKE_OPENAI_API_BASE (default http://127.0.0.1:8190)
through a shared helper, auto-start the canned server from the local_testing and
llm_translation conftests when nothing is already serving, and extend the server
with a Triton embeddings route and a slow-endpoint delay so the triton and
latency-timeout tests run fully offline. The deliberately broken fallback URL is
left as-is so fallback handling still has a failing upstream

* fix: ignore non-loopback FAKE_OPENAI_API_BASE so the local mock is used in CI

* fix: drop 0.0.0.0 from loopback hosts, an unreliable client connect target

* fix(tests): keep fake OpenAI mock alive across xdist workers

ensure_fake_openai_endpoint registered atexit on the worker that spawned
the subprocess, so under -n 4 the first worker to drain its queue would
terminate the shared mock while siblings were still hitting it. Detach
the child via start_new_session and drop the per-worker teardown; reuse
on /health handles re-runs and CI containers clean up themselves
blake-hamm added a commit to blake-hamm/bhamm-lab that referenced this pull request Jun 28, 2026
…to v1.90.0 (#232)

This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [https://github.com/BerriAI/litellm.git](https://github.com/BerriAI/litellm) | minor | `v1.89.4` → `v1.90.0` |

---

### Release Notes

<details>
<summary>BerriAI/litellm (https://github.com/BerriAI/litellm.git)</summary>

### [`v1.90.0`](https://github.com/BerriAI/litellm/releases/tag/v1.90.0)

[Compare Source](BerriAI/litellm@v1.89.4...v1.90.0-rc.1)

#### Verify Docker Image Signature

All LiteLLM Docker images are signed with [cosign](https://docs.sigstore.dev/cosign/overview/). Every release is signed with the same key introduced in [commit `0112e53`](BerriAI/litellm@0112e53).

**Verify using the pinned commit hash (recommended):**

A commit hash is cryptographically immutable, so this is the strongest way to ensure you are using the original signing key:

```bash
cosign verify \
  --key https://raw.githubusercontent.com/BerriAI/litellm/0112e53046018d726492c814b3644b7d376029d0/cosign.pub \
  ghcr.io/berriai/litellm:v1.90.0
```

**Verify using the release tag (convenience):**

Tags are protected in this repository and resolve to the same key. This option is easier to read but relies on tag protection rules:

```bash
cosign verify \
  --key https://raw.githubusercontent.com/BerriAI/litellm/v1.90.0/cosign.pub \
  ghcr.io/berriai/litellm:v1.90.0
```

Expected output:

```
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - The signatures were verified against the specified public key
```

***

#### What's Changed

- fix(responses-bridge): map system-only chat request to system input item by [@&#8203;milan-berri](https://github.com/milan-berri) in [#&#8203;29817](BerriAI/litellm#29817)
- feat(bedrock): forward strict and additionalProperties to Converse toolSpec by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;29814](BerriAI/litellm#29814)
- fix(mcp): highlight MCP cards red when the logged-in user is missing per-user env vars by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;29856](BerriAI/litellm#29856)
- feat(ui): add budget duration to edit team member form by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;29717](BerriAI/litellm#29717)
- fix(ui): make workflow runs page fill full width by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29868](BerriAI/litellm#29868)
- feat: standardize rate limit errors with category, rate\_limit\_type, model, and llm\_provider fields by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;27687](BerriAI/litellm#27687)
- fix(ui): default guardrails page to the Guardrails tab by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29872](BerriAI/litellm#29872)
- docs(readme): add Deploy on AWS/GCP Terraform section and fix deploy button rendering by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;29879](BerriAI/litellm#29879)
- refactor(bedrock): build Converse toolSpec via a BedrockToolSpec dict subclass by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;29869](BerriAI/litellm#29869)
- feat(litellm): add models and repository layers by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;29686](BerriAI/litellm#29686)
- feat(ui): include internal routes in the dashboard's generated OpenAPI types by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;29885](BerriAI/litellm#29885)
- feat(proxy): publish /v2/model/info in Swagger OpenAPI spec by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;29900](BerriAI/litellm#29900)
- refactor(ui): single source of truth for migrated-page routing by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;29949](BerriAI/litellm#29949)
- fix(ui/model-hub): render provider icons on the public model hub by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29958](BerriAI/litellm#29958)
- fix(ui): keep create guardrail modal open on outside click by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29871](BerriAI/litellm#29871)
- fix(ui): label default key type as "Full Access" on key edit page by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29870](BerriAI/litellm#29870)
- fix(ui): unify migrated-route URLs and migrate the API Reference page by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;29953](BerriAI/litellm#29953)
- fix(mcp): let non-creator users OAuth into OBO-mode MCP servers from the Tools page by [@&#8203;tin-berri](https://github.com/tin-berri) in [#&#8203;29867](BerriAI/litellm#29867)
- Litellm oss staging 080626 by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;29932](BerriAI/litellm#29932)
- feat(galileo): add health check support for UI callback test by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;29908](BerriAI/litellm#29908)
- fix(model-management): allow deleting a BYOK model after its team is deleted by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29875](BerriAI/litellm#29875)
- feat(jwt-auth): opt-in fallback to DB team on unresolved JWT claim by [@&#8203;milan-berri](https://github.com/milan-berri) in [#&#8203;28913](BerriAI/litellm#28913)
- fix(team\_endpoints): don't block /team/update on unchanged team budget by [@&#8203;milan-berri](https://github.com/milan-berri) in [#&#8203;29525](BerriAI/litellm#29525)
- fix(fireworks): enable tool calling for glm-5p1 in model cost map by [@&#8203;milan-berri](https://github.com/milan-berri) in [#&#8203;29697](BerriAI/litellm#29697)
- fix(vertex): propagate Vertex AI metadata in streaming success callbacks by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;29899](BerriAI/litellm#29899)
- fix(ui): show team projects to internal users on key creation by [@&#8203;milan-berri](https://github.com/milan-berri) in [#&#8203;28855](BerriAI/litellm#28855)
- build(deps): bump pyjwt to 2.13.0 and ws override to 8.20.1 by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29982](BerriAI/litellm#29982)
- fix(team-management): delete a team's BYOK models when the team is deleted by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29977](BerriAI/litellm#29977)
- feat(vantage): include organization metadata in FOCUS Tags export by [@&#8203;milan-berri](https://github.com/milan-berri) in [#&#8203;28184](BerriAI/litellm#28184)
- fix(guardrails): read CrowdStrike AIDR identity from both metadata bags by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29991](BerriAI/litellm#29991)
- fix(mcp): mirror upstream token lifetime instead of forcing a 1h OBO expiry by [@&#8203;tin-berri](https://github.com/tin-berri) in [#&#8203;29951](BerriAI/litellm#29951)
- feat(azure\_ai): add MAI-Image-2.5 image generation support by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;29688](BerriAI/litellm#29688)
- fix(mcp): load MCP tool configuration tools via the OBO/passthrough-aware GET path by [@&#8203;tin-berri](https://github.com/tin-berri) in [#&#8203;29960](BerriAI/litellm#29960)
- fix(team): reserve team budget raises for proxy admins on /team/update by [@&#8203;milan-berri](https://github.com/milan-berri) in [#&#8203;30030](BerriAI/litellm#30030)
- test(ui): data-driven App Router migration E2E smoke (default + server-root-path) by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;29974](BerriAI/litellm#29974)
- fix(proxy): extend response headers hook to streaming, TTS, image gen, and pass-through by [@&#8203;michelligabriele](https://github.com/michelligabriele) in [#&#8203;24232](BerriAI/litellm#24232)
- chore(ui): remove dead App Router route stubs under (dashboard) by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30045](BerriAI/litellm#30045)
- fix(ui/mcp): reset OAuth state on create-server modal close so a prior server's token no longer leaks into the next add-server session by [@&#8203;tin-berri](https://github.com/tin-berri) in [#&#8203;30000](BerriAI/litellm#30000)
- fix(mcp): allow team access-group grants in OAuth authorize/token access check by [@&#8203;tin-berri](https://github.com/tin-berri) in [#&#8203;30041](BerriAI/litellm#30041)
- docs(security): require a reproduction video for vulnerability reports by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30063](BerriAI/litellm#30063)
- feat(ui): add admin flag to disable in-product UI nudges for everyone by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;29796](BerriAI/litellm#29796)
- chore(ui): remove dead dashboard files and unused dependencies by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30047](BerriAI/litellm#30047)
- fix(proxy): authorize batch files using upload target\_model\_names (LIT-3593) by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30009](BerriAI/litellm#30009)
- Add Claude Fable 5 across Anthropic, Bedrock, Vertex AI, and Azure AI by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30064](BerriAI/litellm#30064)
- Add Claude Fable 5 cost map entries (data-only hotfix for the hosted map) by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30076](BerriAI/litellm#30076)
- fix(caching): restore stored prompt\_tokens on embedding cache hits instead of recomputing by [@&#8203;michelligabriele](https://github.com/michelligabriele) in [#&#8203;30046](BerriAI/litellm#30046)
- Litellm oss 090626 by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30021](BerriAI/litellm#30021)
- fix(proxy): self-heal startup/reload prisma reads on engine disconnect by [@&#8203;michelligabriele](https://github.com/michelligabriele) in [#&#8203;28803](BerriAI/litellm#28803)
- chore(ui): make knip recognize .mjs scripts and openapi-typescript by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30052](BerriAI/litellm#30052)
- fix(register\_model): preserve built-in cache pricing when registering custom overrides under unmapped keys by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30044](BerriAI/litellm#30044)
- \[internal copy of [#&#8203;28007](BerriAI/litellm#28007)] Fix/gcp model garden streaming by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;28363](BerriAI/litellm#28363)
- feat(cli): per-agent `lite claude` / `codex` / `opencode` commands that wrap coding agents through the proxy by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;29850](BerriAI/litellm#29850)
- fix(callbacks): forward callback\_settings to callback initializers and guard consumers against non-dict values by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30161](BerriAI/litellm#30161)
- fix(mcp): drop orphaned per-user credential rows when an MCP server is deleted by [@&#8203;tin-berri](https://github.com/tin-berri) in [#&#8203;30141](BerriAI/litellm#30141)
- fix(proxy): recover from cached-plan errors by reconnecting the Prisma client by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;29983](BerriAI/litellm#29983)
- feat(proxy): add option to disable server-side prepared statements for DB lookups by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;29984](BerriAI/litellm#29984)
- fix(release): stop backport releases from overwriting the latest badge by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30005](BerriAI/litellm#30005)
- feat: add conventional commits and coding guidelines by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30159](BerriAI/litellm#30159)
- fix(proxy): return 5xx on DB infra errors during auth; reserve 401 for genuine auth failures by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;29986](BerriAI/litellm#29986)
- fix(ui): dev server 404s on migrated-page links because uiBase hardcodes /ui by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30169](BerriAI/litellm#30169)
- refactor(ui): consolidate dashboard to one shell in the (dashboard) layout by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30166](BerriAI/litellm#30166)
- fix(proxy): align /v1/model/info with router deployments by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30025](BerriAI/litellm#30025)
- fix: completion\_cost AttributeError on streaming Anthropic web\_search responses ([#&#8203;26153](BerriAI/litellm#26153)) by [@&#8203;ishaan-berri](https://github.com/ishaan-berri) in [#&#8203;27346](BerriAI/litellm#27346)
- \[internal copy of [#&#8203;30137](BerriAI/litellm#30137)] perf(realtime): eliminate redundant per-frame JSON work on OpenAI realtime relay by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30142](BerriAI/litellm#30142)
- feat(bedrock): aws\_bedrock\_project\_id for bedrock-mantle project / workspace association by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30163](BerriAI/litellm#30163)
- chore(hooks): enforce Conventional Commits and Conventional Branches by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30174](BerriAI/litellm#30174)
- feat(rate-limiter): allow opting out of v3 TPM reservation and Redis circuit breaker by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30211](BerriAI/litellm#30211)
- feat(spend\_logs): opt-in native Postgres partitioning for SpendLogs retention by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;29466](BerriAI/litellm#29466)
- feat(ui): migrate playground to path routing and colocate its files by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30185](BerriAI/litellm#30185)
- feat(ui): migrate projects and access-groups to path routes by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30226](BerriAI/litellm#30226)
- fix(proxy): coalesce NULL rollup metrics in aggregated daily-activity by [@&#8203;michelligabriele](https://github.com/michelligabriele) in [#&#8203;30151](BerriAI/litellm#30151)
- fix(anthropic\_passthrough): resolve costing model from message\_start chunk, litellm\_params and model\_group instead of 'unknown' by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30160](BerriAI/litellm#30160)
- feat(ui): migrate budgets, workflows, and guardrails-monitor to path routes by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30236](BerriAI/litellm#30236)
- feat(ui): migrate mcp-servers, search-tools, tag-management, vector-stores, and memory to path routes by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30261](BerriAI/litellm#30261)
- fix(a2a): forward agent\_extra\_headers through completion bridge by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;28277](BerriAI/litellm#28277)
- fix(gemini-live): forward audio buffer commit and correct Vertex PCM rate by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;29946](BerriAI/litellm#29946)
- fix(proxy): skip double-wrapping unified batch output file ids on retrieve by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30011](BerriAI/litellm#30011)
- feat: litellm oss 110626 by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30202](BerriAI/litellm#30202)
- fix(docker): copy only runtime artifacts into the final image by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30243](BerriAI/litellm#30243)
- feat(proxy): enforce key/team guardrails on bedrock passthrough routes by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30194](BerriAI/litellm#30194)
- feat(gemini): forward web search tools in image generation by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30119](BerriAI/litellm#30119)
- fix: bedrock mantle fixes by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30083](BerriAI/litellm#30083)
- feat(proxy): add require\_managed\_files setting for file uploads by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30186](BerriAI/litellm#30186)
- fix(mcp): honor server\_id for REST tool calls with shared upstream URLs by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30184](BerriAI/litellm#30184)
- fix(responses): presidio PII masking for Azure WebSocket and streaming by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30003](BerriAI/litellm#30003)
- feat(passthrough): add configurable pass-through request timeouts by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30266](BerriAI/litellm#30266)
- fix(google\_genai): preserve complete SSE events in Vertex/Gemini image streaming by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30270](BerriAI/litellm#30270)
- fix(proxy): populate access\_via\_team\_ids on /v1/model/info by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30274](BerriAI/litellm#30274)
- chore(oss): litellm oss staging 120626 by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30292](BerriAI/litellm#30292)
- feat(ui): migrate policies, guardrails, prompts, tool-policies, and skills to path routes by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30263](BerriAI/litellm#30263)
- feat(ui): migrate caching, cost-tracking, transform-request, ui-theme, and logs to path routes by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30267](BerriAI/litellm#30267)
- fix(ui): gate dashboard layout on ui config load so deep links work under SERVER\_ROOT\_PATH by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30312](BerriAI/litellm#30312)
- feat(ui): migrate admin-panel, logging-and-alerts, model-hub-table, and usage to path routes by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30268](BerriAI/litellm#30268)
- fix(otel): cap metric attribute cardinality with include/exclude lists by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30257](BerriAI/litellm#30257)
- fix(proxy): grace-period key rotation 401s; return deprecated-key lookup result directly by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30327](BerriAI/litellm#30327)
- chore(deps): bump vitest, brace-expansion, pypdf and tornado by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30220](BerriAI/litellm#30220)
- refactor(ui): remove unreachable /chat page by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30178](BerriAI/litellm#30178)
- feat(ui): migrate agents and router-settings to path routes by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30323](BerriAI/litellm#30323)
- feat: strengthen coding conventions in CLAUDE.md by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30333](BerriAI/litellm#30333)
- feat(ui): cut the users page over to the /ui/users path route by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30334](BerriAI/litellm#30334)
- feat: ruff strict-rule suppressions baseline gate by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30303](BerriAI/litellm#30303)
- feat(guardrails): add Cisco AI Defense integration ([#&#8203;28249](BerriAI/litellm#28249)) by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30338](BerriAI/litellm#30338)
- chore(ui): remove dead UI components unreferenced by any page by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30340](BerriAI/litellm#30340)
- ci: add osv-scanner lockfile scan workflow by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30222](BerriAI/litellm#30222)
- fix(otel): record full error message on standard exception event in otel v2 by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30380](BerriAI/litellm#30380)
- test(fireworks): mock whisper transcription tests instead of live calls by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30391](BerriAI/litellm#30391)
- build(ui): pin esbuild to 0.28.1 via overrides by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30390](BerriAI/litellm#30390)
- feat(ui): cut the organizations page over to the /ui/organizations path route by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30336](BerriAI/litellm#30336)
- fix(proxy): support SMTP implicit SSL (port 465) by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30395](BerriAI/litellm#30395)
- fix(mcp): default Linear MCP registry entry to streamable HTTP by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30396](BerriAI/litellm#30396)
- fix(ui): stop Virtual Keys page from infinite render loop by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30397](BerriAI/litellm#30397)
- fix(streaming): guard raise\_on\_model\_repetition against empty choices by [@&#8203;shivamrawat1](https://github.com/shivamrawat1) in [#&#8203;30485](BerriAI/litellm#30485)
- feat(otel-v2): emit the 6 gen\_ai.client.\* metrics at parity with v1 by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30326](BerriAI/litellm#30326)
- fix(mcp): drop phantom 401 span on delegated OAuth2 tool calls by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30494](BerriAI/litellm#30494)
- feat(ui): cut the teams page over to the /ui/teams path route by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30343](BerriAI/litellm#30343)
- fix(integrations): cap Anthropic cache\_control injection at 4 blocks by [@&#8203;shivamrawat1](https://github.com/shivamrawat1) in [#&#8203;30480](BerriAI/litellm#30480)
- chore(codecov): add Batches, Videos, and Realtime components by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30517](BerriAI/litellm#30517)
- test(batches): move orphan tests into tests/test\_litellm for CI coverage by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30510](BerriAI/litellm#30510)
- fix(guardrails): run pre\_call hook once for model-level guardrails by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30543](BerriAI/litellm#30543)
- fix(guardrails): stop re-initializing DB guardrails on every poll by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30542](BerriAI/litellm#30542)
- chore(oss): litellm oss staging 150626 by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30463](BerriAI/litellm#30463)
- ci(lint): add blanket-noqa, dataclass-default, and unused-noqa Ruff rules by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30516](BerriAI/litellm#30516)
- ci: ratchet lint and type-check gates (ruff preview, ANN, mypy, basedpyright) by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30379](BerriAI/litellm#30379)
- fix(proxy): allow internal roles to access vector store CRUD routes by [@&#8203;shivamrawat1](https://github.com/shivamrawat1) in [#&#8203;30503](BerriAI/litellm#30503)
- fix(otel): stamp gen\_ai.input/output.messages on v2 spans by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30548](BerriAI/litellm#30548)
- fix(otel): export v2 gen\_ai client metrics to the configured meter provider by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30549](BerriAI/litellm#30549)
- fix(bedrock): preserve cache\_control for ARN models in /v1/messages adapter by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;29823](BerriAI/litellm#29823)
- fix: greatly increase basedpyright slack by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30563](BerriAI/litellm#30563)
- fix(budget): recompute budget\_reset\_at when budget\_duration changes on /budget/update by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30555](BerriAI/litellm#30555)
- fix(otel): accept UPPER\_SNAKE\_CASE OTEL\_INSTRUMENTATION\_GENAI\_CAPTURE\_MESSAGE\_CONTENT in v2 by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30562](BerriAI/litellm#30562)
- chore(lint): remove PLR0915 too-many-statements ruff rule by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30574](BerriAI/litellm#30574)
- ci(lint): ratcheted type-discipline gate (mutable collections, casts, guards, kwargs, suppressions) by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30500](BerriAI/litellm#30500)
- feat(proxy): add verification\_uri\_complete to CLI SSO device flow by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30571](BerriAI/litellm#30571)
- chore: litellm oss staging160626 by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30527](BerriAI/litellm#30527)
- fix(guardrails): return 400 not 500 when AIM blocks a request by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30573](BerriAI/litellm#30573)
- ci(lint): grandfather any-discipline with a per-file ratchet budget (50% headroom) by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30582](BerriAI/litellm#30582)
- fix(audio): don't override explicit response\_format with verbose\_json by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30599](BerriAI/litellm#30599)
- fix(anthropic): price and surface response service\_tier in cost tracking by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30558](BerriAI/litellm#30558)
- feat: add dev and wildcard proxy configs for local testing by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30556](BerriAI/litellm#30556)
- fix(proxy): list public team model name in /v1/models by [@&#8203;ishaan-berri](https://github.com/ishaan-berri) in [#&#8203;30588](BerriAI/litellm#30588)
- ci: drop mypy entirely, standardize type checking on basedpyright by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30648](BerriAI/litellm#30648)
- feat(guardrails): surface OpenAI moderation violation\_categories on guardrail traces by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30659](BerriAI/litellm#30659)
- fix(proxy): resolve list files credentials from team BYOK deployments by [@&#8203;shivamrawat1](https://github.com/shivamrawat1) in [#&#8203;30495](BerriAI/litellm#30495)
- feat(proxy): add --max\_requests\_before\_restart\_jitter to stagger worker restarts by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30601](BerriAI/litellm#30601)
- fix(health): correct bedrock embedding health checks by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30583](BerriAI/litellm#30583)
- test: harden remaining pass-through CI flakes (image-gen spend poll, ruby assistants timeout) by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30685](BerriAI/litellm#30685)
- test(pass\_through): harden vertex spendlog poll against transient empty reads by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30683](BerriAI/litellm#30683)
- fix(cost): stop non-string service\_tier from silently dropping cost tracking by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30690](BerriAI/litellm#30690)
- feat(proxy): warn at startup when custom\_auth skips common\_checks enforcement by [@&#8203;tin-berri](https://github.com/tin-berri) in [#&#8203;30665](BerriAI/litellm#30665)
- fix(pod\_lock): release cron lock by matching async\_set\_cache JSON encoding by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30600](BerriAI/litellm#30600)
- ci: run a local fake OpenAI endpoint instead of the shared Railway mock by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30695](BerriAI/litellm#30695)
- ci(windows): pin uv to Python 3.11 so it ignores the preinstalled 3.14 by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30704](BerriAI/litellm#30704)
- feat(ui): migrate models page to App Router path route by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30677](BerriAI/litellm#30677)
- refactor(ui): remove orphaned pass-through-settings route by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30692](BerriAI/litellm#30692)
- fix(cost): stop non-string response service\_tier from dropping cost tracking by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30706](BerriAI/litellm#30706)
- feat(agent-shin): automated PR/issue triage, low-quality auto-close, and review-gate label lifecycle by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30433](BerriAI/litellm#30433)
- chore: litellm oss 170626 by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30637](BerriAI/litellm#30637)
- fix(bedrock\_mantle): add SigV4 fallback to chat completions auth by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30714](BerriAI/litellm#30714)
- feat(search): add TinyFish as search provider by [@&#8203;simantak-dabhade](https://github.com/simantak-dabhade) in [#&#8203;30634](BerriAI/litellm#30634)
- feat(ui): migrate old usage report to App Router path route by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30694](BerriAI/litellm#30694)
- fix(proxy): enforce budgets against authoritative DB spend when the cross-pod counter is stale by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30684](BerriAI/litellm#30684)
- chore(ci): remove Agent Shin pull\_request\_target workflows by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30784](BerriAI/litellm#30784)
- chore: litellm oss staging by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30745](BerriAI/litellm#30745)
- ci(zizmor): also run on litellm\_internal\_staging by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30789](BerriAI/litellm#30789)
- fix(test): drop references to removed Agent Shin workflows by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30791](https://github.com/BerriAI/litellm/pull/30791)
- chore: remove in-product survey and Claude Code feedback nudges by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30773](https://github.com/BerriAI/litellm/pull/30773)
- feat(ui): migrate api-keys landing to App Router path route by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30699](https://github.com/BerriAI/litellm/pull/30699)
- feat(proxy): configurable response headers and login-page hint by [@&#8203;yucheng-berri](https://github.com/yucheng-berri) in [#&#8203;30792](https://github.com/BerriAI/litellm/pull/30792)
- ci(zizmor): gate PRs on medium+ findings and clear existing ones by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30797](https://github.com/BerriAI/litellm/pull/30797)
- fix(proxy): use e.request\_data for logging\_obj in ModifyResponseException streaming passthrough by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30800](https://github.com/BerriAI/litellm/pull/30800)
- chore: make pr template linear portion clearer by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30766](https://github.com/BerriAI/litellm/pull/30766)
- chore(typing): add boto3/botocore stubs so basedpyright resolves the AWS SDK by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30815](https://github.com/BerriAI/litellm/pull/30815)
- fix(otel): one v2 logger owns the global provider; scope tenant OTLP creds per exporter by [@&#8203;yucheng-berri](https://github.com/yucheng-berri) in [#&#8203;30590](https://github.com/BerriAI/litellm/pull/30590)
- fix(passthrough): recover output tokens for interrupted anthropic streams by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30787](https://github.com/BerriAI/litellm/pull/30787)
- fix(proxy): record partial spend on the failure row for interrupted streams by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30788](https://github.com/BerriAI/litellm/pull/30788)
- fix(ui): repoint dead usage guide link to cost tracking docs by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30859](https://github.com/BerriAI/litellm/pull/30859)
- fix(ui): warn that team models are deleted in the delete-team modal by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29990](https://github.com/BerriAI/litellm/pull/29990)
- feat(caching): add valkey-semantic cache backend and fix semantic cache scope keys by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30675](https://github.com/BerriAI/litellm/pull/30675)
- test(ui): isolate OldTeams delete-warning tests from leaked mock by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30871](https://github.com/BerriAI/litellm/pull/30871)
- feat: add lint-gate target and truncation-proof summary to the strict ruff gate by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30877](https://github.com/BerriAI/litellm/pull/30877)
- chore(ui): rebuild ui for release by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30894](https://github.com/BerriAI/litellm/pull/30894)
- chore(ci): bump deps by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30899](https://github.com/BerriAI/litellm/pull/30899)
- fix(watsonx): wrap string embedding input in array for WatsonX API by [@&#8203;shivamrawat1](https://github.com/shivamrawat1) in [#&#8203;30897](https://github.com/BerriAI/litellm/pull/30897)
- test: point router/completion/triton tests at the local fake OpenAI endpoint by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30900](https://github.com/BerriAI/litellm/pull/30900)
- feat(sandbox): e2b code execution primitive by [@&#8203;krrish-berri-2](https://github.com/krrish-berri-2) in [#&#8203;30898](https://github.com/BerriAI/litellm/pull/30898)
- fix(ui): source api-keys identity from useAuthorized to stop "User ID is not set" by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30903](https://github.com/BerriAI/litellm/pull/30903)
- chore(ui): rebuild ui by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30906](https://github.com/BerriAI/litellm/pull/30906)
- chore(ci): promote internal staging to main by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30907](https://github.com/BerriAI/litellm/pull/30907)
- fix(redis): prevent forcing SSLConnection when ssl=False in connection pool by [@&#8203;Jacopos311](https://github.com/Jacopos311) in [#&#8203;30770](https://github.com/BerriAI/litellm/pull/30770)
- fix(proxy): log UI setup failures instead of silently swallowing by [@&#8203;sarvesh1327](https://github.com/sarvesh1327) in [#&#8203;30819](https://github.com/BerriAI/litellm/pull/30819)

#### New Contributors

- [@&#8203;simantak-dabhade](https://github.com/simantak-dabhade) made their first contribution in [#&#8203;30634](BerriAI/litellm#30634)
- [@&#8203;Jacopos311](https://github.com/Jacopos311) made their first contribution in [#&#8203;30770](https://github.com/BerriAI/litellm/pull/30770)
- [@&#8203;sarvesh1327](https://github.com/sarvesh1327) made their first contribution in [#&#8203;30819](https://github.com/BerriAI/litellm/pull/30819)

**Full Changelog**: <BerriAI/litellm@v1.89.0...v1.90.0>

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMjAuMCIsInVwZGF0ZWRJblZlciI6IjQzLjIyMC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->

Co-authored-by: Renovate Bot <[email protected]>
Reviewed-on: https://codeberg.org/blake-hamm/bhamm-lab/pulls/232
blake-hamm added a commit to blake-hamm/bhamm-lab that referenced this pull request Jun 28, 2026
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [ghcr.io/berriai/litellm](https://images.chainguard.dev/directory/image/wolfi-base/overview) ([source](https://github.com/BerriAI/litellm)) | final | minor | `v1.85.1` → `v1.90.0` |

---

### Release Notes

<details>
<summary>BerriAI/litellm (ghcr.io/berriai/litellm)</summary>

### [`v1.90.0`](https://github.com/BerriAI/litellm/releases/tag/v1.90.0)

[Compare Source](https://github.com/BerriAI/litellm/compare/v1.90.0...v1.90.0)

##### Verify Docker Image Signature

All LiteLLM Docker images are signed with [cosign](https://docs.sigstore.dev/cosign/overview/). Every release is signed with the same key introduced in [commit `0112e53`](https://github.com/BerriAI/litellm/commit/0112e53046018d726492c814b3644b7d376029d0).

**Verify using the pinned commit hash (recommended):**

A commit hash is cryptographically immutable, so this is the strongest way to ensure you are using the original signing key:

```bash
cosign verify \
  --key https://raw.githubusercontent.com/BerriAI/litellm/0112e53046018d726492c814b3644b7d376029d0/cosign.pub \
  ghcr.io/berriai/litellm:v1.90.0
```

**Verify using the release tag (convenience):**

Tags are protected in this repository and resolve to the same key. This option is easier to read but relies on tag protection rules:

```bash
cosign verify \
  --key https://raw.githubusercontent.com/BerriAI/litellm/v1.90.0/cosign.pub \
  ghcr.io/berriai/litellm:v1.90.0
```

Expected output:

```
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - The signatures were verified against the specified public key
```

***

##### What's Changed

- fix(responses-bridge): map system-only chat request to system input item by [@&#8203;milan-berri](https://github.com/milan-berri) in [#&#8203;29817](https://github.com/BerriAI/litellm/pull/29817)
- feat(bedrock): forward strict and additionalProperties to Converse toolSpec by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;29814](https://github.com/BerriAI/litellm/pull/29814)
- fix(mcp): highlight MCP cards red when the logged-in user is missing per-user env vars by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;29856](https://github.com/BerriAI/litellm/pull/29856)
- feat(ui): add budget duration to edit team member form by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;29717](https://github.com/BerriAI/litellm/pull/29717)
- fix(ui): make workflow runs page fill full width by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29868](https://github.com/BerriAI/litellm/pull/29868)
- feat: standardize rate limit errors with category, rate\_limit\_type, model, and llm\_provider fields by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;27687](https://github.com/BerriAI/litellm/pull/27687)
- fix(ui): default guardrails page to the Guardrails tab by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29872](https://github.com/BerriAI/litellm/pull/29872)
- docs(readme): add Deploy on AWS/GCP Terraform section and fix deploy button rendering by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;29879](https://github.com/BerriAI/litellm/pull/29879)
- refactor(bedrock): build Converse toolSpec via a BedrockToolSpec dict subclass by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;29869](https://github.com/BerriAI/litellm/pull/29869)
- feat(litellm): add models and repository layers by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;29686](https://github.com/BerriAI/litellm/pull/29686)
- feat(ui): include internal routes in the dashboard's generated OpenAPI types by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;29885](https://github.com/BerriAI/litellm/pull/29885)
- feat(proxy): publish /v2/model/info in Swagger OpenAPI spec by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;29900](https://github.com/BerriAI/litellm/pull/29900)
- refactor(ui): single source of truth for migrated-page routing by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;29949](https://github.com/BerriAI/litellm/pull/29949)
- fix(ui/model-hub): render provider icons on the public model hub by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29958](https://github.com/BerriAI/litellm/pull/29958)
- fix(ui): keep create guardrail modal open on outside click by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29871](https://github.com/BerriAI/litellm/pull/29871)
- fix(ui): label default key type as "Full Access" on key edit page by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29870](https://github.com/BerriAI/litellm/pull/29870)
- fix(ui): unify migrated-route URLs and migrate the API Reference page by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;29953](https://github.com/BerriAI/litellm/pull/29953)
- fix(mcp): let non-creator users OAuth into OBO-mode MCP servers from the Tools page by [@&#8203;tin-berri](https://github.com/tin-berri) in [#&#8203;29867](https://github.com/BerriAI/litellm/pull/29867)
- Litellm oss staging 080626 by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;29932](https://github.com/BerriAI/litellm/pull/29932)
- feat(galileo): add health check support for UI callback test by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;29908](https://github.com/BerriAI/litellm/pull/29908)
- fix(model-management): allow deleting a BYOK model after its team is deleted by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29875](https://github.com/BerriAI/litellm/pull/29875)
- feat(jwt-auth): opt-in fallback to DB team on unresolved JWT claim by [@&#8203;milan-berri](https://github.com/milan-berri) in [#&#8203;28913](https://github.com/BerriAI/litellm/pull/28913)
- fix(team\_endpoints): don't block /team/update on unchanged team budget by [@&#8203;milan-berri](https://github.com/milan-berri) in [#&#8203;29525](https://github.com/BerriAI/litellm/pull/29525)
- fix(fireworks): enable tool calling for glm-5p1 in model cost map by [@&#8203;milan-berri](https://github.com/milan-berri) in [#&#8203;29697](https://github.com/BerriAI/litellm/pull/29697)
- fix(vertex): propagate Vertex AI metadata in streaming success callbacks by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;29899](https://github.com/BerriAI/litellm/pull/29899)
- fix(ui): show team projects to internal users on key creation by [@&#8203;milan-berri](https://github.com/milan-berri) in [#&#8203;28855](https://github.com/BerriAI/litellm/pull/28855)
- build(deps): bump pyjwt to 2.13.0 and ws override to 8.20.1 by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29982](https://github.com/BerriAI/litellm/pull/29982)
- fix(team-management): delete a team's BYOK models when the team is deleted by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29977](https://github.com/BerriAI/litellm/pull/29977)
- feat(vantage): include organization metadata in FOCUS Tags export by [@&#8203;milan-berri](https://github.com/milan-berri) in [#&#8203;28184](https://github.com/BerriAI/litellm/pull/28184)
- fix(guardrails): read CrowdStrike AIDR identity from both metadata bags by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29991](https://github.com/BerriAI/litellm/pull/29991)
- fix(mcp): mirror upstream token lifetime instead of forcing a 1h OBO expiry by [@&#8203;tin-berri](https://github.com/tin-berri) in [#&#8203;29951](https://github.com/BerriAI/litellm/pull/29951)
- feat(azure\_ai): add MAI-Image-2.5 image generation support by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;29688](https://github.com/BerriAI/litellm/pull/29688)
- fix(mcp): load MCP tool configuration tools via the OBO/passthrough-aware GET path by [@&#8203;tin-berri](https://github.com/tin-berri) in [#&#8203;29960](https://github.com/BerriAI/litellm/pull/29960)
- fix(team): reserve team budget raises for proxy admins on /team/update by [@&#8203;milan-berri](https://github.com/milan-berri) in [#&#8203;30030](https://github.com/BerriAI/litellm/pull/30030)
- test(ui): data-driven App Router migration E2E smoke (default + server-root-path) by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;29974](https://github.com/BerriAI/litellm/pull/29974)
- fix(proxy): extend response headers hook to streaming, TTS, image gen, and pass-through by [@&#8203;michelligabriele](https://github.com/michelligabriele) in [#&#8203;24232](https://github.com/BerriAI/litellm/pull/24232)
- chore(ui): remove dead App Router route stubs under (dashboard) by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30045](https://github.com/BerriAI/litellm/pull/30045)
- fix(ui/mcp): reset OAuth state on create-server modal close so a prior server's token no longer leaks into the next add-server session by [@&#8203;tin-berri](https://github.com/tin-berri) in [#&#8203;30000](https://github.com/BerriAI/litellm/pull/30000)
- fix(mcp): allow team access-group grants in OAuth authorize/token access check by [@&#8203;tin-berri](https://github.com/tin-berri) in [#&#8203;30041](https://github.com/BerriAI/litellm/pull/30041)
- docs(security): require a reproduction video for vulnerability reports by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30063](https://github.com/BerriAI/litellm/pull/30063)
- feat(ui): add admin flag to disable in-product UI nudges for everyone by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;29796](https://github.com/BerriAI/litellm/pull/29796)
- chore(ui): remove dead dashboard files and unused dependencies by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30047](https://github.com/BerriAI/litellm/pull/30047)
- fix(proxy): authorize batch files using upload target\_model\_names (LIT-3593) by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30009](https://github.com/BerriAI/litellm/pull/30009)
- Add Claude Fable 5 across Anthropic, Bedrock, Vertex AI, and Azure AI by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30064](https://github.com/BerriAI/litellm/pull/30064)
- Add Claude Fable 5 cost map entries (data-only hotfix for the hosted map) by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30076](https://github.com/BerriAI/litellm/pull/30076)
- fix(caching): restore stored prompt\_tokens on embedding cache hits instead of recomputing by [@&#8203;michelligabriele](https://github.com/michelligabriele) in [#&#8203;30046](https://github.com/BerriAI/litellm/pull/30046)
- Litellm oss 090626 by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30021](https://github.com/BerriAI/litellm/pull/30021)
- fix(proxy): self-heal startup/reload prisma reads on engine disconnect by [@&#8203;michelligabriele](https://github.com/michelligabriele) in [#&#8203;28803](https://github.com/BerriAI/litellm/pull/28803)
- chore(ui): make knip recognize .mjs scripts and openapi-typescript by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30052](https://github.com/BerriAI/litellm/pull/30052)
- fix(register\_model): preserve built-in cache pricing when registering custom overrides under unmapped keys by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30044](https://github.com/BerriAI/litellm/pull/30044)
- \[internal copy of [#&#8203;28007](https://github.com/BerriAI/litellm/issues/28007)] Fix/gcp model garden streaming by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;28363](https://github.com/BerriAI/litellm/pull/28363)
- feat(cli): per-agent `lite claude` / `codex` / `opencode` commands that wrap coding agents through the proxy by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;29850](https://github.com/BerriAI/litellm/pull/29850)
- fix(callbacks): forward callback\_settings to callback initializers and guard consumers against non-dict values by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30161](https://github.com/BerriAI/litellm/pull/30161)
- fix(mcp): drop orphaned per-user credential rows when an MCP server is deleted by [@&#8203;tin-berri](https://github.com/tin-berri) in [#&#8203;30141](https://github.com/BerriAI/litellm/pull/30141)
- fix(proxy): recover from cached-plan errors by reconnecting the Prisma client by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;29983](https://github.com/BerriAI/litellm/pull/29983)
- feat(proxy): add option to disable server-side prepared statements for DB lookups by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;29984](https://github.com/BerriAI/litellm/pull/29984)
- fix(release): stop backport releases from overwriting the latest badge by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30005](https://github.com/BerriAI/litellm/pull/30005)
- feat: add conventional commits and coding guidelines by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30159](https://github.com/BerriAI/litellm/pull/30159)
- fix(proxy): return 5xx on DB infra errors during auth; reserve 401 for genuine auth failures by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;29986](https://github.com/BerriAI/litellm/pull/29986)
- fix(ui): dev server 404s on migrated-page links because uiBase hardcodes /ui by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30169](https://github.com/BerriAI/litellm/pull/30169)
- refactor(ui): consolidate dashboard to one shell in the (dashboard) layout by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30166](https://github.com/BerriAI/litellm/pull/30166)
- fix(proxy): align /v1/model/info with router deployments by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30025](https://github.com/BerriAI/litellm/pull/30025)
- fix: completion\_cost AttributeError on streaming Anthropic web\_search responses ([#&#8203;26153](https://github.com/BerriAI/litellm/issues/26153)) by [@&#8203;ishaan-berri](https://github.com/ishaan-berri) in [#&#8203;27346](https://github.com/BerriAI/litellm/pull/27346)
- \[internal copy of [#&#8203;30137](https://github.com/BerriAI/litellm/issues/30137)] perf(realtime): eliminate redundant per-frame JSON work on OpenAI realtime relay by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30142](https://github.com/BerriAI/litellm/pull/30142)
- feat(bedrock): aws\_bedrock\_project\_id for bedrock-mantle project / workspace association by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30163](https://github.com/BerriAI/litellm/pull/30163)
- chore(hooks): enforce Conventional Commits and Conventional Branches by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30174](https://github.com/BerriAI/litellm/pull/30174)
- feat(rate-limiter): allow opting out of v3 TPM reservation and Redis circuit breaker by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30211](https://github.com/BerriAI/litellm/pull/30211)
- feat(spend\_logs): opt-in native Postgres partitioning for SpendLogs retention by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;29466](https://github.com/BerriAI/litellm/pull/29466)
- feat(ui): migrate playground to path routing and colocate its files by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30185](https://github.com/BerriAI/litellm/pull/30185)
- feat(ui): migrate projects and access-groups to path routes by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30226](https://github.com/BerriAI/litellm/pull/30226)
- fix(proxy): coalesce NULL rollup metrics in aggregated daily-activity by [@&#8203;michelligabriele](https://github.com/michelligabriele) in [#&#8203;30151](https://github.com/BerriAI/litellm/pull/30151)
- fix(anthropic\_passthrough): resolve costing model from message\_start chunk, litellm\_params and model\_group instead of 'unknown' by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30160](https://github.com/BerriAI/litellm/pull/30160)
- feat(ui): migrate budgets, workflows, and guardrails-monitor to path routes by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30236](https://github.com/BerriAI/litellm/pull/30236)
- feat(ui): migrate mcp-servers, search-tools, tag-management, vector-stores, and memory to path routes by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30261](https://github.com/BerriAI/litellm/pull/30261)
- fix(a2a): forward agent\_extra\_headers through completion bridge by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;28277](https://github.com/BerriAI/litellm/pull/28277)
- fix(gemini-live): forward audio buffer commit and correct Vertex PCM rate by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;29946](https://github.com/BerriAI/litellm/pull/29946)
- fix(proxy): skip double-wrapping unified batch output file ids on retrieve by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30011](https://github.com/BerriAI/litellm/pull/30011)
- feat: litellm oss 110626 by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30202](https://github.com/BerriAI/litellm/pull/30202)
- fix(docker): copy only runtime artifacts into the final image by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30243](https://github.com/BerriAI/litellm/pull/30243)
- feat(proxy): enforce key/team guardrails on bedrock passthrough routes by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30194](https://github.com/BerriAI/litellm/pull/30194)
- feat(gemini): forward web search tools in image generation by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30119](https://github.com/BerriAI/litellm/pull/30119)
- fix: bedrock mantle fixes by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30083](https://github.com/BerriAI/litellm/pull/30083)
- feat(proxy): add require\_managed\_files setting for file uploads by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30186](https://github.com/BerriAI/litellm/pull/30186)
- fix(mcp): honor server\_id for REST tool calls with shared upstream URLs by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30184](https://github.com/BerriAI/litellm/pull/30184)
- fix(responses): presidio PII masking for Azure WebSocket and streaming by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30003](https://github.com/BerriAI/litellm/pull/30003)
- feat(passthrough): add configurable pass-through request timeouts by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30266](https://github.com/BerriAI/litellm/pull/30266)
- fix(google\_genai): preserve complete SSE events in Vertex/Gemini image streaming by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30270](https://github.com/BerriAI/litellm/pull/30270)
- fix(proxy): populate access\_via\_team\_ids on /v1/model/info by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30274](https://github.com/BerriAI/litellm/pull/30274)
- chore(oss): litellm oss staging 120626 by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30292](https://github.com/BerriAI/litellm/pull/30292)
- feat(ui): migrate policies, guardrails, prompts, tool-policies, and skills to path routes by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30263](https://github.com/BerriAI/litellm/pull/30263)
- feat(ui): migrate caching, cost-tracking, transform-request, ui-theme, and logs to path routes by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30267](https://github.com/BerriAI/litellm/pull/30267)
- fix(ui): gate dashboard layout on ui config load so deep links work under SERVER\_ROOT\_PATH by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30312](https://github.com/BerriAI/litellm/pull/30312)
- feat(ui): migrate admin-panel, logging-and-alerts, model-hub-table, and usage to path routes by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30268](https://github.com/BerriAI/litellm/pull/30268)
- fix(otel): cap metric attribute cardinality with include/exclude lists by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30257](https://github.com/BerriAI/litellm/pull/30257)
- fix(proxy): grace-period key rotation 401s; return deprecated-key lookup result directly by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30327](https://github.com/BerriAI/litellm/pull/30327)
- chore(deps): bump vitest, brace-expansion, pypdf and tornado by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30220](https://github.com/BerriAI/litellm/pull/30220)
- refactor(ui): remove unreachable /chat page by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30178](https://github.com/BerriAI/litellm/pull/30178)
- feat(ui): migrate agents and router-settings to path routes by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30323](https://github.com/BerriAI/litellm/pull/30323)
- feat: strengthen coding conventions in CLAUDE.md by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30333](https://github.com/BerriAI/litellm/pull/30333)
- feat(ui): cut the users page over to the /ui/users path route by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30334](https://github.com/BerriAI/litellm/pull/30334)
- feat: ruff strict-rule suppressions baseline gate by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30303](https://github.com/BerriAI/litellm/pull/30303)
- feat(guardrails): add Cisco AI Defense integration ([#&#8203;28249](https://github.com/BerriAI/litellm/issues/28249)) by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30338](https://github.com/BerriAI/litellm/pull/30338)
- chore(ui): remove dead UI components unreferenced by any page by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30340](https://github.com/BerriAI/litellm/pull/30340)
- ci: add osv-scanner lockfile scan workflow by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30222](https://github.com/BerriAI/litellm/pull/30222)
- fix(otel): record full error message on standard exception event in otel v2 by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30380](https://github.com/BerriAI/litellm/pull/30380)
- test(fireworks): mock whisper transcription tests instead of live calls by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30391](https://github.com/BerriAI/litellm/pull/30391)
- build(ui): pin esbuild to 0.28.1 via overrides by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30390](https://github.com/BerriAI/litellm/pull/30390)
- feat(ui): cut the organizations page over to the /ui/organizations path route by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30336](https://github.com/BerriAI/litellm/pull/30336)
- fix(proxy): support SMTP implicit SSL (port 465) by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30395](https://github.com/BerriAI/litellm/pull/30395)
- fix(mcp): default Linear MCP registry entry to streamable HTTP by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30396](https://github.com/BerriAI/litellm/pull/30396)
- fix(ui): stop Virtual Keys page from infinite render loop by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30397](https://github.com/BerriAI/litellm/pull/30397)
- fix(streaming): guard raise\_on\_model\_repetition against empty choices by [@&#8203;shivamrawat1](https://github.com/shivamrawat1) in [#&#8203;30485](https://github.com/BerriAI/litellm/pull/30485)
- feat(otel-v2): emit the 6 gen\_ai.client.\* metrics at parity with v1 by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30326](https://github.com/BerriAI/litellm/pull/30326)
- fix(mcp): drop phantom 401 span on delegated OAuth2 tool calls by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30494](https://github.com/BerriAI/litellm/pull/30494)
- feat(ui): cut the teams page over to the /ui/teams path route by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30343](https://github.com/BerriAI/litellm/pull/30343)
- fix(integrations): cap Anthropic cache\_control injection at 4 blocks by [@&#8203;shivamrawat1](https://github.com/shivamrawat1) in [#&#8203;30480](https://github.com/BerriAI/litellm/pull/30480)
- chore(codecov): add Batches, Videos, and Realtime components by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30517](https://github.com/BerriAI/litellm/pull/30517)
- test(batches): move orphan tests into tests/test\_litellm for CI coverage by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30510](https://github.com/BerriAI/litellm/pull/30510)
- fix(guardrails): run pre\_call hook once for model-level guardrails by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30543](https://github.com/BerriAI/litellm/pull/30543)
- fix(guardrails): stop re-initializing DB guardrails on every poll by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30542](https://github.com/BerriAI/litellm/pull/30542)
- chore(oss): litellm oss staging 150626 by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30463](https://github.com/BerriAI/litellm/pull/30463)
- ci(lint): add blanket-noqa, dataclass-default, and unused-noqa Ruff rules by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30516](https://github.com/BerriAI/litellm/pull/30516)
- ci: ratchet lint and type-check gates (ruff preview, ANN, mypy, basedpyright) by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30379](https://github.com/BerriAI/litellm/pull/30379)
- fix(proxy): allow internal roles to access vector store CRUD routes by [@&#8203;shivamrawat1](https://github.com/shivamrawat1) in [#&#8203;30503](https://github.com/BerriAI/litellm/pull/30503)
- fix(otel): stamp gen\_ai.input/output.messages on v2 spans by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30548](https://github.com/BerriAI/litellm/pull/30548)
- fix(otel): export v2 gen\_ai client metrics to the configured meter provider by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30549](https://github.com/BerriAI/litellm/pull/30549)
- fix(bedrock): preserve cache\_control for ARN models in /v1/messages adapter by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;29823](https://github.com/BerriAI/litellm/pull/29823)
- fix: greatly increase basedpyright slack by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30563](https://github.com/BerriAI/litellm/pull/30563)
- fix(budget): recompute budget\_reset\_at when budget\_duration changes on /budget/update by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30555](https://github.com/BerriAI/litellm/pull/30555)
- fix(otel): accept UPPER\_SNAKE\_CASE OTEL\_INSTRUMENTATION\_GENAI\_CAPTURE\_MESSAGE\_CONTENT in v2 by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30562](https://github.com/BerriAI/litellm/pull/30562)
- chore(lint): remove PLR0915 too-many-statements ruff rule by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30574](https://github.com/BerriAI/litellm/pull/30574)
- ci(lint): ratcheted type-discipline gate (mutable collections, casts, guards, kwargs, suppressions) by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30500](https://github.com/BerriAI/litellm/pull/30500)
- feat(proxy): add verification\_uri\_complete to CLI SSO device flow by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30571](https://github.com/BerriAI/litellm/pull/30571)
- chore: litellm oss staging160626 by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30527](https://github.com/BerriAI/litellm/pull/30527)
- fix(guardrails): return 400 not 500 when AIM blocks a request by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30573](https://github.com/BerriAI/litellm/pull/30573)
- ci(lint): grandfather any-discipline with a per-file ratchet budget (50% headroom) by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30582](https://github.com/BerriAI/litellm/pull/30582)
- fix(audio): don't override explicit response\_format with verbose\_json by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30599](https://github.com/BerriAI/litellm/pull/30599)
- fix(anthropic): price and surface response service\_tier in cost tracking by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30558](https://github.com/BerriAI/litellm/pull/30558)
- feat: add dev and wildcard proxy configs for local testing by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30556](https://github.com/BerriAI/litellm/pull/30556)
- fix(proxy): list public team model name in /v1/models by [@&#8203;ishaan-berri](https://github.com/ishaan-berri) in [#&#8203;30588](https://github.com/BerriAI/litellm/pull/30588)
- ci: drop mypy entirely, standardize type checking on basedpyright by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30648](https://github.com/BerriAI/litellm/pull/30648)
- feat(guardrails): surface OpenAI moderation violation\_categories on guardrail traces by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30659](https://github.com/BerriAI/litellm/pull/30659)
- fix(proxy): resolve list files credentials from team BYOK deployments by [@&#8203;shivamrawat1](https://github.com/shivamrawat1) in [#&#8203;30495](https://github.com/BerriAI/litellm/pull/30495)
- feat(proxy): add --max\_requests\_before\_restart\_jitter to stagger worker restarts by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30601](https://github.com/BerriAI/litellm/pull/30601)
- fix(health): correct bedrock embedding health checks by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30583](https://github.com/BerriAI/litellm/pull/30583)
- test: harden remaining pass-through CI flakes (image-gen spend poll, ruby assistants timeout) by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30685](https://github.com/BerriAI/litellm/pull/30685)
- test(pass\_through): harden vertex spendlog poll against transient empty reads by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30683](https://github.com/BerriAI/litellm/pull/30683)
- fix(cost): stop non-string service\_tier from silently dropping cost tracking by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30690](https://github.com/BerriAI/litellm/pull/30690)
- feat(proxy): warn at startup when custom\_auth skips common\_checks enforcement by [@&#8203;tin-berri](https://github.com/tin-berri) in [#&#8203;30665](https://github.com/BerriAI/litellm/pull/30665)
- fix(pod\_lock): release cron lock by matching async\_set\_cache JSON encoding by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30600](https://github.com/BerriAI/litellm/pull/30600)
- ci: run a local fake OpenAI endpoint instead of the shared Railway mock by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30695](https://github.com/BerriAI/litellm/pull/30695)
- ci(windows): pin uv to Python 3.11 so it ignores the preinstalled 3.14 by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30704](https://github.com/BerriAI/litellm/pull/30704)
- feat(ui): migrate models page to App Router path route by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30677](https://github.com/BerriAI/litellm/pull/30677)
- refactor(ui): remove orphaned pass-through-settings route by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30692](https://github.com/BerriAI/litellm/pull/30692)
- fix(cost): stop non-string response service\_tier from dropping cost tracking by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30706](https://github.com/BerriAI/litellm/pull/30706)
- feat(agent-shin): automated PR/issue triage, low-quality auto-close, and review-gate label lifecycle by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30433](https://github.com/BerriAI/litellm/pull/30433)
- chore: litellm oss 170626 by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30637](https://github.com/BerriAI/litellm/pull/30637)
- fix(bedrock\_mantle): add SigV4 fallback to chat completions auth by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30714](https://github.com/BerriAI/litellm/pull/30714)
- feat(search): add TinyFish as search provider by [@&#8203;simantak-dabhade](https://github.com/simantak-dabhade) in [#&#8203;30634](https://github.com/BerriAI/litellm/pull/30634)
- feat(ui): migrate old usage report to App Router path route by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30694](https://github.com/BerriAI/litellm/pull/30694)
- fix(proxy): enforce budgets against authoritative DB spend when the cross-pod counter is stale by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30684](https://github.com/BerriAI/litellm/pull/30684)
- chore(ci): remove Agent Shin pull\_request\_target workflows by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30784](https://github.com/BerriAI/litellm/pull/30784)
- chore: litellm oss staging by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30745](https://github.com/BerriAI/litellm/pull/30745)
- ci(zizmor): also run on litellm\_internal\_staging by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30789](https://github.com/BerriAI/litellm/pull/30789)
- fix(test): drop references to removed Agent Shin workflows by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30791](https://github.com/BerriAI/litellm/pull/30791)
- chore: remove in-product survey and Claude Code feedback nudges by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30773](https://github.com/BerriAI/litellm/pull/30773)
- feat(ui): migrate api-keys landing to App Router path route by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30699](https://github.com/BerriAI/litellm/pull/30699)
- feat(proxy): configurable response headers and login-page hint by [@&#8203;yucheng-berri](https://github.com/yucheng-berri) in [#&#8203;30792](https://github.com/BerriAI/litellm/pull/30792)
- ci(zizmor): gate PRs on medium+ findings and clear existing ones by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30797](https://github.com/BerriAI/litellm/pull/30797)
- fix(proxy): use e.request\_data for logging\_obj in ModifyResponseException streaming passthrough by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30800](https://github.com/BerriAI/litellm/pull/30800)
- chore: make pr template linear portion clearer by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30766](https://github.com/BerriAI/litellm/pull/30766)
- chore(typing): add boto3/botocore stubs so basedpyright resolves the AWS SDK by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30815](https://github.com/BerriAI/litellm/pull/30815)
- fix(otel): one v2 logger owns the global provider; scope tenant OTLP creds per exporter by [@&#8203;yucheng-berri](https://github.com/yucheng-berri) in [#&#8203;30590](https://github.com/BerriAI/litellm/pull/30590)
- fix(passthrough): recover output tokens for interrupted anthropic streams by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30787](https://github.com/BerriAI/litellm/pull/30787)
- fix(proxy): record partial spend on the failure row for interrupted streams by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30788](https://github.com/BerriAI/litellm/pull/30788)
- fix(ui): repoint dead usage guide link to cost tracking docs by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30859](https://github.com/BerriAI/litellm/pull/30859)
- fix(ui): warn that team models are deleted in the delete-team modal by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29990](https://github.com/BerriAI/litellm/pull/29990)
- feat(caching): add valkey-semantic cache backend and fix semantic cache scope keys by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30675](https://github.com/BerriAI/litellm/pull/30675)
- test(ui): isolate OldTeams delete-warning tests from leaked mock by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30871](https://github.com/BerriAI/litellm/pull/30871)
- feat: add lint-gate target and truncation-proof summary to the strict ruff gate by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30877](https://github.com/BerriAI/litellm/pull/30877)
- chore(ui): rebuild ui for release by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30894](https://github.com/BerriAI/litellm/pull/30894)
- chore(ci): bump deps by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30899](https://github.com/BerriAI/litellm/pull/30899)
- fix(watsonx): wrap string embedding input in array for WatsonX API by [@&#8203;shivamrawat1](https://github.com/shivamrawat1) in [#&#8203;30897](https://github.com/BerriAI/litellm/pull/30897)
- test: point router/completion/triton tests at the local fake OpenAI endpoint by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30900](https://github.com/BerriAI/litellm/pull/30900)
- feat(sandbox): e2b code execution primitive by [@&#8203;krrish-berri-2](https://github.com/krrish-berri-2) in [#&#8203;30898](https://github.com/BerriAI/litellm/pull/30898)
- fix(ui): source api-keys identity from useAuthorized to stop "User ID is not set" by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30903](https://github.com/BerriAI/litellm/pull/30903)
- chore(ui): rebuild ui by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30906](https://github.com/BerriAI/litellm/pull/30906)
- chore(ci): promote internal staging to main by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30907](https://github.com/BerriAI/litellm/pull/30907)
- fix(redis): prevent forcing SSLConnection when ssl=False in connection pool by [@&#8203;Jacopos311](https://github.com/Jacopos311) in [#&#8203;30770](https://github.com/BerriAI/litellm/pull/30770)
- fix(proxy): log UI setup failures instead of silently swallowing by [@&#8203;sarvesh1327](https://github.com/sarvesh1327) in [#&#8203;30819](https://github.com/BerriAI/litellm/pull/30819)

##### New Contributors

- [@&#8203;simantak-dabhade](https://github.com/simantak-dabhade) made their first contribution in [#&#8203;30634](https://github.com/BerriAI/litellm/pull/30634)
- [@&#8203;Jacopos311](https://github.com/Jacopos311) made their first contribution in [#&#8203;30770](https://github.com/BerriAI/litellm/pull/30770)
- [@&#8203;sarvesh1327](https://github.com/sarvesh1327) made their first contribution in [#&#8203;30819](https://github.com/BerriAI/litellm/pull/30819)

**Full Changelog**: <https://github.com/BerriAI/litellm/compare/v1.89.0...v1.90.0>

### [`v1.90.0`](https://github.com/BerriAI/litellm/releases/tag/v1.90.0)

[Compare Source](https://github.com/BerriAI/litellm/compare/v1.89.4...v1.90.0)

##### Verify Docker Image Signature

All LiteLLM Docker images are signed with [cosign](https://docs.sigstore.dev/cosign/overview/). Every release is signed with the same key introduced in [commit `0112e53`](https://github.com/BerriAI/litellm/commit/0112e53046018d726492c814b3644b7d376029d0).

**Verify using the pinned commit hash (recommended):**

A commit hash is cryptographically immutable, so this is the strongest way to ensure you are using the original signing key:

```bash
cosign verify \
  --key https://raw.githubusercontent.com/BerriAI/litellm/0112e53046018d726492c814b3644b7d376029d0/cosign.pub \
  ghcr.io/berriai/litellm:v1.90.0
```

**Verify using the release tag (convenience):**

Tags are protected in this repository and resolve to the same key. This option is easier to read but relies on tag protection rules:

```bash
cosign verify \
  --key https://raw.githubusercontent.com/BerriAI/litellm/v1.90.0/cosign.pub \
  ghcr.io/berriai/litellm:v1.90.0
```

Expected output:

```
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - The signatures were verified against the specified public key
```

***

##### What's Changed

- fix(responses-bridge): map system-only chat request to system input item by [@&#8203;milan-berri](https://github.com/milan-berri) in [#&#8203;29817](https://github.com/BerriAI/litellm/pull/29817)
- feat(bedrock): forward strict and additionalProperties to Converse toolSpec by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;29814](https://github.com/BerriAI/litellm/pull/29814)
- fix(mcp): highlight MCP cards red when the logged-in user is missing per-user env vars by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;29856](https://github.com/BerriAI/litellm/pull/29856)
- feat(ui): add budget duration to edit team member form by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;29717](https://github.com/BerriAI/litellm/pull/29717)
- fix(ui): make workflow runs page fill full width by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29868](https://github.com/BerriAI/litellm/pull/29868)
- feat: standardize rate limit errors with category, rate\_limit\_type, model, and llm\_provider fields by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;27687](https://github.com/BerriAI/litellm/pull/27687)
- fix(ui): default guardrails page to the Guardrails tab by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29872](https://github.com/BerriAI/litellm/pull/29872)
- docs(readme): add Deploy on AWS/GCP Terraform section and fix deploy button rendering by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;29879](https://github.com/BerriAI/litellm/pull/29879)
- refactor(bedrock): build Converse toolSpec via a BedrockToolSpec dict subclass by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;29869](https://github.com/BerriAI/litellm/pull/29869)
- feat(litellm): add models and repository layers by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;29686](https://github.com/BerriAI/litellm/pull/29686)
- feat(ui): include internal routes in the dashboard's generated OpenAPI types by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;29885](https://github.com/BerriAI/litellm/pull/29885)
- feat(proxy): publish /v2/model/info in Swagger OpenAPI spec by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;29900](https://github.com/BerriAI/litellm/pull/29900)
- refactor(ui): single source of truth for migrated-page routing by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;29949](https://github.com/BerriAI/litellm/pull/29949)
- fix(ui/model-hub): render provider icons on the public model hub by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29958](https://github.com/BerriAI/litellm/pull/29958)
- fix(ui): keep create guardrail modal open on outside click by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29871](https://github.com/BerriAI/litellm/pull/29871)
- fix(ui): label default key type as "Full Access" on key edit page by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29870](https://github.com/BerriAI/litellm/pull/29870)
- fix(ui): unify migrated-route URLs and migrate the API Reference page by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;29953](https://github.com/BerriAI/litellm/pull/29953)
- fix(mcp): let non-creator users OAuth into OBO-mode MCP servers from the Tools page by [@&#8203;tin-berri](https://github.com/tin-berri) in [#&#8203;29867](https://github.com/BerriAI/litellm/pull/29867)
- Litellm oss staging 080626 by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;29932](https://github.com/BerriAI/litellm/pull/29932)
- feat(galileo): add health check support for UI callback test by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;29908](https://github.com/BerriAI/litellm/pull/29908)
- fix(model-management): allow deleting a BYOK model after its team is deleted by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29875](https://github.com/BerriAI/litellm/pull/29875)
- feat(jwt-auth): opt-in fallback to DB team on unresolved JWT claim by [@&#8203;milan-berri](https://github.com/milan-berri) in [#&#8203;28913](https://github.com/BerriAI/litellm/pull/28913)
- fix(team\_endpoints): don't block /team/update on unchanged team budget by [@&#8203;milan-berri](https://github.com/milan-berri) in [#&#8203;29525](https://github.com/BerriAI/litellm/pull/29525)
- fix(fireworks): enable tool calling for glm-5p1 in model cost map by [@&#8203;milan-berri](https://github.com/milan-berri) in [#&#8203;29697](https://github.com/BerriAI/litellm/pull/29697)
- fix(vertex): propagate Vertex AI metadata in streaming success callbacks by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;29899](https://github.com/BerriAI/litellm/pull/29899)
- fix(ui): show team projects to internal users on key creation by [@&#8203;milan-berri](https://github.com/milan-berri) in [#&#8203;28855](https://github.com/BerriAI/litellm/pull/28855)
- build(deps): bump pyjwt to 2.13.0 and ws override to 8.20.1 by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29982](https://github.com/BerriAI/litellm/pull/29982)
- fix(team-management): delete a team's BYOK models when the team is deleted by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29977](https://github.com/BerriAI/litellm/pull/29977)
- feat(vantage): include organization metadata in FOCUS Tags export by [@&#8203;milan-berri](https://github.com/milan-berri) in [#&#8203;28184](https://github.com/BerriAI/litellm/pull/28184)
- fix(guardrails): read CrowdStrike AIDR identity from both metadata bags by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;29991](https://github.com/BerriAI/litellm/pull/29991)
- fix(mcp): mirror upstream token lifetime instead of forcing a 1h OBO expiry by [@&#8203;tin-berri](https://github.com/tin-berri) in [#&#8203;29951](https://github.com/BerriAI/litellm/pull/29951)
- feat(azure\_ai): add MAI-Image-2.5 image generation support by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;29688](https://github.com/BerriAI/litellm/pull/29688)
- fix(mcp): load MCP tool configuration tools via the OBO/passthrough-aware GET path by [@&#8203;tin-berri](https://github.com/tin-berri) in [#&#8203;29960](https://github.com/BerriAI/litellm/pull/29960)
- fix(team): reserve team budget raises for proxy admins on /team/update by [@&#8203;milan-berri](https://github.com/milan-berri) in [#&#8203;30030](https://github.com/BerriAI/litellm/pull/30030)
- test(ui): data-driven App Router migration E2E smoke (default + server-root-path) by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;29974](https://github.com/BerriAI/litellm/pull/29974)
- fix(proxy): extend response headers hook to streaming, TTS, image gen, and pass-through by [@&#8203;michelligabriele](https://github.com/michelligabriele) in [#&#8203;24232](https://github.com/BerriAI/litellm/pull/24232)
- chore(ui): remove dead App Router route stubs under (dashboard) by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30045](https://github.com/BerriAI/litellm/pull/30045)
- fix(ui/mcp): reset OAuth state on create-server modal close so a prior server's token no longer leaks into the next add-server session by [@&#8203;tin-berri](https://github.com/tin-berri) in [#&#8203;30000](https://github.com/BerriAI/litellm/pull/30000)
- fix(mcp): allow team access-group grants in OAuth authorize/token access check by [@&#8203;tin-berri](https://github.com/tin-berri) in [#&#8203;30041](https://github.com/BerriAI/litellm/pull/30041)
- docs(security): require a reproduction video for vulnerability reports by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30063](https://github.com/BerriAI/litellm/pull/30063)
- feat(ui): add admin flag to disable in-product UI nudges for everyone by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;29796](https://github.com/BerriAI/litellm/pull/29796)
- chore(ui): remove dead dashboard files and unused dependencies by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30047](https://github.com/BerriAI/litellm/pull/30047)
- fix(proxy): authorize batch files using upload target\_model\_names (LIT-3593) by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30009](https://github.com/BerriAI/litellm/pull/30009)
- Add Claude Fable 5 across Anthropic, Bedrock, Vertex AI, and Azure AI by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30064](https://github.com/BerriAI/litellm/pull/30064)
- Add Claude Fable 5 cost map entries (data-only hotfix for the hosted map) by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30076](https://github.com/BerriAI/litellm/pull/30076)
- fix(caching): restore stored prompt\_tokens on embedding cache hits instead of recomputing by [@&#8203;michelligabriele](https://github.com/michelligabriele) in [#&#8203;30046](https://github.com/BerriAI/litellm/pull/30046)
- Litellm oss 090626 by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30021](https://github.com/BerriAI/litellm/pull/30021)
- fix(proxy): self-heal startup/reload prisma reads on engine disconnect by [@&#8203;michelligabriele](https://github.com/michelligabriele) in [#&#8203;28803](https://github.com/BerriAI/litellm/pull/28803)
- chore(ui): make knip recognize .mjs scripts and openapi-typescript by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30052](https://github.com/BerriAI/litellm/pull/30052)
- fix(register\_model): preserve built-in cache pricing when registering custom overrides under unmapped keys by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30044](https://github.com/BerriAI/litellm/pull/30044)
- \[internal copy of [#&#8203;28007](https://github.com/BerriAI/litellm/issues/28007)] Fix/gcp model garden streaming by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;28363](https://github.com/BerriAI/litellm/pull/28363)
- feat(cli): per-agent `lite claude` / `codex` / `opencode` commands that wrap coding agents through the proxy by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;29850](https://github.com/BerriAI/litellm/pull/29850)
- fix(callbacks): forward callback\_settings to callback initializers and guard consumers against non-dict values by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30161](https://github.com/BerriAI/litellm/pull/30161)
- fix(mcp): drop orphaned per-user credential rows when an MCP server is deleted by [@&#8203;tin-berri](https://github.com/tin-berri) in [#&#8203;30141](https://github.com/BerriAI/litellm/pull/30141)
- fix(proxy): recover from cached-plan errors by reconnecting the Prisma client by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;29983](https://github.com/BerriAI/litellm/pull/29983)
- feat(proxy): add option to disable server-side prepared statements for DB lookups by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;29984](https://github.com/BerriAI/litellm/pull/29984)
- fix(release): stop backport releases from overwriting the latest badge by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30005](https://github.com/BerriAI/litellm/pull/30005)
- feat: add conventional commits and coding guidelines by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30159](https://github.com/BerriAI/litellm/pull/30159)
- fix(proxy): return 5xx on DB infra errors during auth; reserve 401 for genuine auth failures by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;29986](https://github.com/BerriAI/litellm/pull/29986)
- fix(ui): dev server 404s on migrated-page links because uiBase hardcodes /ui by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30169](https://github.com/BerriAI/litellm/pull/30169)
- refactor(ui): consolidate dashboard to one shell in the (dashboard) layout by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30166](https://github.com/BerriAI/litellm/pull/30166)
- fix(proxy): align /v1/model/info with router deployments by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30025](https://github.com/BerriAI/litellm/pull/30025)
- fix: completion\_cost AttributeError on streaming Anthropic web\_search responses ([#&#8203;26153](https://github.com/BerriAI/litellm/issues/26153)) by [@&#8203;ishaan-berri](https://github.com/ishaan-berri) in [#&#8203;27346](https://github.com/BerriAI/litellm/pull/27346)
- \[internal copy of [#&#8203;30137](https://github.com/BerriAI/litellm/issues/30137)] perf(realtime): eliminate redundant per-frame JSON work on OpenAI realtime relay by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30142](https://github.com/BerriAI/litellm/pull/30142)
- feat(bedrock): aws\_bedrock\_project\_id for bedrock-mantle project / workspace association by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30163](https://github.com/BerriAI/litellm/pull/30163)
- chore(hooks): enforce Conventional Commits and Conventional Branches by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30174](https://github.com/BerriAI/litellm/pull/30174)
- feat(rate-limiter): allow opting out of v3 TPM reservation and Redis circuit breaker by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30211](https://github.com/BerriAI/litellm/pull/30211)
- feat(spend\_logs): opt-in native Postgres partitioning for SpendLogs retention by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;29466](https://github.com/BerriAI/litellm/pull/29466)
- feat(ui): migrate playground to path routing and colocate its files by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30185](https://github.com/BerriAI/litellm/pull/30185)
- feat(ui): migrate projects and access-groups to path routes by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30226](https://github.com/BerriAI/litellm/pull/30226)
- fix(proxy): coalesce NULL rollup metrics in aggregated daily-activity by [@&#8203;michelligabriele](https://github.com/michelligabriele) in [#&#8203;30151](https://github.com/BerriAI/litellm/pull/30151)
- fix(anthropic\_passthrough): resolve costing model from message\_start chunk, litellm\_params and model\_group instead of 'unknown' by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30160](https://github.com/BerriAI/litellm/pull/30160)
- feat(ui): migrate budgets, workflows, and guardrails-monitor to path routes by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30236](https://github.com/BerriAI/litellm/pull/30236)
- feat(ui): migrate mcp-servers, search-tools, tag-management, vector-stores, and memory to path routes by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30261](https://github.com/BerriAI/litellm/pull/30261)
- fix(a2a): forward agent\_extra\_headers through completion bridge by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;28277](https://github.com/BerriAI/litellm/pull/28277)
- fix(gemini-live): forward audio buffer commit and correct Vertex PCM rate by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;29946](https://github.com/BerriAI/litellm/pull/29946)
- fix(proxy): skip double-wrapping unified batch output file ids on retrieve by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30011](https://github.com/BerriAI/litellm/pull/30011)
- feat: litellm oss 110626 by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30202](https://github.com/BerriAI/litellm/pull/30202)
- fix(docker): copy only runtime artifacts into the final image by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30243](https://github.com/BerriAI/litellm/pull/30243)
- feat(proxy): enforce key/team guardrails on bedrock passthrough routes by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30194](https://github.com/BerriAI/litellm/pull/30194)
- feat(gemini): forward web search tools in image generation by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30119](https://github.com/BerriAI/litellm/pull/30119)
- fix: bedrock mantle fixes by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30083](https://github.com/BerriAI/litellm/pull/30083)
- feat(proxy): add require\_managed\_files setting for file uploads by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30186](https://github.com/BerriAI/litellm/pull/30186)
- fix(mcp): honor server\_id for REST tool calls with shared upstream URLs by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30184](https://github.com/BerriAI/litellm/pull/30184)
- fix(responses): presidio PII masking for Azure WebSocket and streaming by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30003](https://github.com/BerriAI/litellm/pull/30003)
- feat(passthrough): add configurable pass-through request timeouts by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30266](https://github.com/BerriAI/litellm/pull/30266)
- fix(google\_genai): preserve complete SSE events in Vertex/Gemini image streaming by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30270](https://github.com/BerriAI/litellm/pull/30270)
- fix(proxy): populate access\_via\_team\_ids on /v1/model/info by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30274](https://github.com/BerriAI/litellm/pull/30274)
- chore(oss): litellm oss staging 120626 by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30292](https://github.com/BerriAI/litellm/pull/30292)
- feat(ui): migrate policies, guardrails, prompts, tool-policies, and skills to path routes by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30263](https://github.com/BerriAI/litellm/pull/30263)
- feat(ui): migrate caching, cost-tracking, transform-request, ui-theme, and logs to path routes by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30267](https://github.com/BerriAI/litellm/pull/30267)
- fix(ui): gate dashboard layout on ui config load so deep links work under SERVER\_ROOT\_PATH by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30312](https://github.com/BerriAI/litellm/pull/30312)
- feat(ui): migrate admin-panel, logging-and-alerts, model-hub-table, and usage to path routes by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30268](https://github.com/BerriAI/litellm/pull/30268)
- fix(otel): cap metric attribute cardinality with include/exclude lists by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30257](https://github.com/BerriAI/litellm/pull/30257)
- fix(proxy): grace-period key rotation 401s; return deprecated-key lookup result directly by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30327](https://github.com/BerriAI/litellm/pull/30327)
- chore(deps): bump vitest, brace-expansion, pypdf and tornado by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30220](https://github.com/BerriAI/litellm/pull/30220)
- refactor(ui): remove unreachable /chat page by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30178](https://github.com/BerriAI/litellm/pull/30178)
- feat(ui): migrate agents and router-settings to path routes by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30323](https://github.com/BerriAI/litellm/pull/30323)
- feat: strengthen coding conventions in CLAUDE.md by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;30333](https://github.com/BerriAI/litellm/pull/30333)
- feat(ui): cut the users page over to the /ui/users path route by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30334](https://github.com/BerriAI/litellm/pull/30334)
- feat: ruff strict-rule suppressions baseline gate by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30303](https://github.com/BerriAI/litellm/pull/30303)
- feat(guardrails): add Cisco AI Defense integration ([#&#8203;28249](https://github.com/BerriAI/litellm/issues/28249)) by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30338](https://github.com/BerriAI/litellm/pull/30338)
- chore(ui): remove dead UI components unreferenced by any page by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30340](https://github.com/BerriAI/litellm/pull/30340)
- ci: add osv-scanner lockfile scan workflow by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30222](https://github.com/BerriAI/litellm/pull/30222)
- fix(otel): record full error message on standard exception event in otel v2 by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30380](https://github.com/BerriAI/litellm/pull/30380)
- test(fireworks): mock whisper transcription tests instead of live calls by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30391](https://github.com/BerriAI/litellm/pull/30391)
- build(ui): pin esbuild to 0.28.1 via overrides by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30390](https://github.com/BerriAI/litellm/pull/30390)
- feat(ui): cut the organizations page over to the /ui/organizations path route by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30336](https://github.com/BerriAI/litellm/pull/30336)
- fix(proxy): support SMTP implicit SSL (port 465) by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;30395](https://github.com/BerriAI/litellm/pull/30395)
- fix(mcp): default Linear MCP registry entry to streamable HTTP by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30396](https://github.com/BerriAI/litellm/pull/30396)
- fix(ui): stop Virtual Keys page from infinite render loop by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30397](https://github.com/BerriAI/litellm/pull/30397)
- fix(streaming): guard raise\_on\_model\_repetition against empty choices by [@&#8203;shivamrawat1](https://github.com/shivamrawat1) in [#&#8203;30485](https://github.com/BerriAI/litellm/pull/30485)
- feat(otel-v2): emit the 6 gen\_ai.client.\* metrics at parity with v1 by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30326](https://github.com/BerriAI/litellm/pull/30326)
- fix(mcp): drop phantom 401 span on delegated OAuth2 tool calls by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30494](https://github.com/BerriAI/litellm/pull/30494)
- feat(ui): cut the teams page over to the /ui/teams path route by [@&#8203;ryan-crabbe-berri](https://github.com/ryan-crabbe-berri) in [#&#8203;30343](https://github.com/BerriAI/litellm/pull/30343)
- fix(integrations): cap Anthropic cache\_control injection at 4 blocks by [@&#8203;shivamrawat1](https://github.com/shivamrawat1) in [#&#8203;30480](https://github.com/BerriAI/litellm/pull/30480)
- chore(codecov): add Batches, Videos, and Realtime components by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30517](https://github.com/BerriAI/litellm/pull/30517)
- test(batches): move orphan tests into tests/test\_litellm for CI coverage by [@&#8203;Sameerlite](https://github.com/Sameerlite) in [#&#8203;30510](https://github.com/BerriAI/litellm/pull/30510)
- fix(guardrails): run pre\_call hook once for model-level guardrails by [@&#8203;yassin-berriai](https://github.com/yassin-berriai) in [#&#8203;30543](http…
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants