Commit graph

44185 commits

Author SHA1 Message Date
ryan-crabbe-berri
f5080dee2e fix(ui): classify the restricted proxy caveat, which keeps the row live
Some checks failed
LiteLLM Rust / rustfmt, clippy, test (push) Has been cancelled
2026-08-20 20:41:32 -07:00
ryan-crabbe-berri
5bbf1452b3 docs(key budgets): state why a swallowed lookup reports unlimited, not unknown
Several of the helpers this reads entities through swallow a read error and
hand back an absence instead of raising. Enforcement calls those same helpers
and acts on that same absence, so a scope reported as unlimited is one no
check will apply on the request the row describes. _Unavailable is for the
helpers that do raise, whose failure leaves a budget that would still gate the
request, and those report unknown.

Pins both halves: a tag whose fetch failed open, and a team whose lookup raised.
2026-08-20 20:27:51 -07:00
ryan-crabbe-berri
6a6e5877d9 test: satisfy the test-quality gates upstream added under ruff-tests and TQ002 2026-08-20 20:12:29 -07:00
ryan-crabbe-berri
a6458b5a22 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_key_budgets_endpoint
# Conflicts:
#	tests/test_litellm/proxy/auth/test_auth_exception_handler.py
2026-08-20 20:01:54 -07:00
Mateo Wang
354f497faf
Merge pull request #37751 from BerriAI/litellm_fal_gpt_image_2_keyed_pricing
fix(fal_ai): price gpt-image-2 per size and quality from request params
2026-08-20 19:51:26 -07:00
ryan-crabbe-berri
d0082eb644 fix(key budgets): withhold the proxy-wide numbers from callers who may not read them
The proxy row's limit and spend cover the whole deployment, not the key
being inspected, and every proxy-wide spend route is admin-only. Reporting
them on a route any key holder can call handed one tenant the total spend of
all of them.

The row still ships, because dropping it would read as "no proxy budget
applies", which is the guess this endpoint exists to remove. Its numbers are
blanked, `spend_state` gains `restricted` so a blank is never mistaken for a
failed read or a zero, and the row reports unknown: a caller who cannot see
the numbers cannot rule the scope out. The proxy budget row is not read from
the database at all for those callers.
2026-08-20 19:50:34 -07:00
Mateo Wang
a66a10b1b5
Merge pull request #37734 from BerriAI/litellm_fix_partial_stream_spend_rows
fix(streaming): price partial-stream spend rows at the real model and keep prompt and cache fields
2026-08-20 19:48:08 -07:00
ryan-crabbe-berri
7ae1005109 fix(key budgets): gate a team mate's key behind the team member permission
Belonging to a key's team is what grants /key/info, and this route reports
far more than /key/info does: the team's, the caller's own membership, the
owning user's, the organization's and the key's tag spend. A member whose
team has not granted /key/{key_id}/budgets could read all of it off someone
else's key. Proxy admins, the calling key itself and keys the caller owns
never reach the team's permission list.

Also pins the two end user failure modes the report has to tell apart: a
lookup that comes back empty still gets max_end_user_budget_id, because auth
falls back to it, while a lookup that raises gets an unknown row, because
both auth call sites wrap that same fallback in the try a raise escapes.
2026-08-20 19:36:34 -07:00
ryan-crabbe-berri
a112ba5f63
test: enforce PT012 so a pytest.raises block cannot hide dead assertions (#37748)
* test: enforce PT012 so a pytest.raises block cannot hide dead assertions

`with pytest.raises(...)` stops at the first statement that raises. Anything
sequenced after it inside the block never runs, so an assertion written there is
never checked and the test still reports green.

Two sites were doing exactly that, and both assertions turned out to be wrong
once they started running. tests/llm_translation/test_prompt_factory.py asserted
the bedrock rejection names "requires at least one non-system message", which
holds. tests/proxy_unit_tests/test_proxy_server.py asserted the prisma startup
failure mentions "httpx.ConnectError", which never appears: the failure is an
httpx.ConnectError whose message is "All connection attempts failed", so that
test now asserts the type. Its DATABASE_URL override moves to monkeypatch, since
the old restore sat below the assertion and leaked the invalid URL into every
later DB test the moment the assertion started being able to fail.

The remaining 72 sites are rewritten without changing what they exercise: setup
that cannot raise moves above the block, a nested `patch` moves outside it, and
bodies with real control flow (a stream drain, an if/else on sync_mode, a
retry loop) move into a local closure the block calls.

Fixing PT012 unmasked two B017s, since ruff only reports a blind
pytest.raises(Exception) once the block holds a single statement.
tests/proxy_unit_tests/test_auth_checks.py narrows to the ProxyException
can_key_call_model actually raises. tests/local_testing/test_completion_cost.py
was asserting vertex_ai/medlm-medium has no cost entry, which stopped being true
at some point; that dead first half is gone and the rest of the test, which
checks medlm pricing resolves above zero, now runs instead of being skipped.

* chore(ci): ratchet TQ004 to 768 after the prisma test moved to monkeypatch
2026-08-20 19:36:26 -07:00
Mateo Wang
a4dd1be53b
Merge pull request #35114 from BerriAI/litellm_fix_messages_stream_cost_cache_tokens
fix(cost): match streamed Messages usage cost to the recorded spend
2026-08-20 19:35:09 -07:00
devin-ai-integration[bot]
f1c4145f86
fix(scim): resolve group members by SSO identity or email before creating a placeholder (#37686)
SCIM group members were matched against litellm user ids only. An identity
provider that lists people by email or by the OIDC subject therefore matched
nothing, and the member fell through to placeholder creation.

Since #37688 made a failed member creation fail the group sync rather than drop
the member, that fallthrough is no longer quiet: the placeholder is created with
user_email set to the member value, the duplicate-email check rejects it, and the
whole group push answers 500. So on current staging a group listing anyone by
their email fails outright, every other member in the payload included.

An unmatched member id is now looked up across sso_user_id and user_email in one
query. Searching either field first would hide a value that names one account by
its SSO identity and another by its email, and hand the group to whichever was
searched first. The two are not compared alike: an email is matched the way
new_user matches one before accepting a new account, case-insensitively, because
matching more strictly than the layer that would reject the placeholder is what
turned an id whose casing differed from the stored email into that same 500. An
SSO identity is matched exactly, since OIDC defines sub as case-sensitive and
nothing folds its case on the way in.

An exact user_id hit is checked the same way rather than trusted outright, since a
value can be one account's id and another's SSO identity or email. That is not a
corner case: the placeholders this bug provisioned are keyed by the very id the
provider keeps pushing, so on a tenant that already has them the placeholder wins
the id lookup and the real account can never be matched. Refusing names the
problem instead of silently landing on the placeholder again. Those rows still
have to be deleted before the real account resolves; making the sync heal itself
needs a trustworthy way to tell a placeholder from an account someone created, and
created_via lives in caller-writable metadata, so it is left to a follow-up.

A value that names more than one account is refused with a 400 naming the id
rather than attributed to one of them.

Removals resolve too, since the roster holds canonical user ids and a directory
removes people by the id it added them with. A removal counts the members one
value names: the id as written when the roster holds it verbatim, which is how an
earlier release recorded a member it could not match, together with the members it
resolves to. Counting only the accounts on the roster keeps someone removable
after a second account takes their email, which resolving table-wide would not,
and counting both ways of naming a member together stops one value revoking two
people when it is one member's canonical id and another's email. A value naming
two of the group's own members is undecidable and fails rather than guessing or
reporting a removal it did not perform.

Resolves LIT-5383

Co-authored-by: Yassin Kortam <yassin@berri.ai>
2026-08-20 19:32:57 -07:00
mateo-berri
0801493347 Match the client-name check to the name the proxy actually stamps
Pre-call processing rewrites request_data["model"] for aliasing and routing, so
matching either key let a routed model count as the client's own name and put the
wrapper model back on an Azure Model Router row.
2026-08-20 19:25:46 -07:00
Mateo Wang
65b4ac012f
Merge pull request #37618 from BerriAI/litellm_lit_5870_passthrough_e2e_pins
test(e2e): pin openai_passthrough routing, cost logging, and file list isolation
2026-08-20 19:22:39 -07:00
mateo-berri
c010bd6a7c Only keep the builder's model when the client did not ask for it
A chunk carrying usage is stored as a pre-restamp copy, so an alias-restamped
stream reaches disconnect billing with its first chunk still on the deployment
model and every later chunk on the client's name. That is the same shape Azure
Model Router produces, and the previous guard read it as a routed model and
left the alias on the row, which is the unpriced name this PR set out to stop.

Compare the assembled model against the name the proxy stamps chunks with, so
the alias goes back to the deployment's model and the routed model stays.
2026-08-20 19:08:11 -07:00
mateo-berri
655d10775c fix(cost): keep mid-stream pricing from leaking a breakdown into the spend log
Pricing a frame through the request's own logging object is what makes custom
deployment pricing work, but _response_cost_calculator does not only return a
number. It also stamps cost_breakdown onto the live logging object, and on a
pricing failure it writes response_cost_failure_debug_information into
model_call_details.

On an ordinary proxy stream that is harmless, because the success handler
recomputes cost_breakdown at end of stream and overwrites whatever the frames
left behind. The pass-through handlers are the problem: they compute their final
cost with a bare completion_cost call and never touch cost_breakdown again, so a
breakdown derived from one mid-stream frame would survive to the end and land in
the spend log's metadata. response_cost itself is unaffected either way, so this
was a reporting surface bug rather than a billing one, but the spend row would
have gone from null to a populated breakdown for a partial frame.

Snapshot both writes and put them back once the cost is read, so pricing a frame
stays a read as far as the rest of the request is concerned. The returned cost is
unchanged, so nothing about the injected usage.cost moves.
2026-08-20 19:01:16 -07:00
yuneng-jiang
35416c702d
test: point the live together_ai suites at a model together still serves (#37746)
Every live together_ai call in CI has answered 503 Service unavailable since
2026-08-20, across two runs 2.5 hours apart, while Together's status page
reported no incident in either window. These are real calls, not replayed
cassettes: the VCR layer runs filter_non_2xx_response, so a 503 is never
written to a cassette and cannot be replayed back.

Qwen/Qwen2.5-7B-Instruct-Turbo does not appear anywhere on Together's monitored
component list, whose Qwen entries are all Qwen3.x, so a model-level outage
there would never surface as an incident. The same 503 already forced
test_basic_rerank_together_ai to be skipped on a different together_ai model,
so per-model 503s are an established failure mode here rather than a platform
outage.

openai/gpt-oss-20b is the cheapest together_ai entry that carries real pricing
and the capabilities these suites exercise, at $0.05/$0.20 per 1M tokens with
function calling, response schema and tool choice. Together monitors it as a
served component. The retired model also carries null pricing in the cost map,
which is its own liability now that unpriced models are blocked.

test_multiple_deployments.py keeps the old id: it is a router fallback list
that is green today, and busting its cassette to prove a point would trade a
passing test for a live call this change cannot vouch for.
2026-08-20 18:53:27 -07:00
yuneng-jiang
60225ab429
test: assert the prefixed model the azure responses bridge now hands back (#37749)
a369cb0da7 made completion() hand the prefixed model back to responses(), so
that responses() running get_llm_provider() a second time becomes a no-op
instead of stripping a prefix the model id owns. That was deliberate, and it
shipped with its own unit test, but it left two older assertions behind still
expecting the bare id.

#37744 corrected the openai one in test_openai.py. This is its azure sibling,
which llm_translation_testing has been failing on ever since.

Only the expected value moves. The neighbouring custom_llm_provider assertion
already passes and stays as it is.
2026-08-20 18:53:23 -07:00
Mateo Wang
4e02e7e404
Merge pull request #37742 from BerriAI/litellm_lit5879_semantic_cache_embedding_timeout
fix(caching): bound the semantic cache embedding lookup so a dead embedding endpoint can't block requests
2026-08-20 18:51:02 -07:00
mateo-berri
101ef7e167 test(cost): cover the chat.completion.chunk and raising-pricer branches
The logging-object pricing applies to streamed /v1/chat/completions too, not
just Anthropic message_delta, so a deployment with negotiated per-token prices
now gets that price in the streamed usage.cost there as well. Nothing asserted
that half. Adds the discounted and the sticker-fallback case for the OpenAI
chunk shape, plus the branch where the pricer raises and the frame falls back
to model-name pricing instead of breaking the stream.
2026-08-20 18:46:38 -07:00
mateo-berri
03a253a1f9 Keep the model Azure Model Router recovered from later chunks
The disconnect billing path was stamping the wrapper's model over whatever
stream_chunk_builder assembled. For Azure Model Router that throws away the
routed model: the proxy deliberately leaves those chunks unrestamped so the
builder can pick the real model off a later chunk, and overwriting it prices
the row at the router alias instead.

Only apply the wrapper's model when the builder did not find a model beyond
the first chunk's, which is every case except Model Router.
2026-08-20 18:45:51 -07:00
Mateo Wang
66a6a09706
Merge pull request #37743 from BerriAI/litellm_cognition_provider_identity
feat(cognition): give Cognition its own provider identity
2026-08-20 18:38:23 -07:00
github-actions[bot]
d5e6a0c9b8 fix(fal_ai): strip provider prefix before keyed cost lookup 2026-08-20 18:36:48 -07:00
mateo-berri
2471e85f54 chore(lint): note why the streamed cost fallback swallows pricing errors 2026-08-20 18:28:59 -07:00
mateo-berri
12ed364e47 Merge branch 'litellm_internal_staging' into litellm_fix_messages_stream_cost_cache_tokens 2026-08-20 18:28:42 -07:00
mateo-berri
d57715bf46 chore(constants): drop the redundant comment on the semantic cache deadline 2026-08-20 18:23:40 -07:00
Mateo Wang
dad4c1a0fb
Merge pull request #37710 from BerriAI/litellm_fix_responses_bridge_incomplete_500
fix(responses_bridge): map incomplete responses to finish_reason length instead of 500
2026-08-20 18:10:29 -07:00
ryan-crabbe-berri
680bcfd8aa
test(lint): ban blind pytest.raises(Exception) with ruff B017 (#37731)
* test(lint): ban blind pytest.raises(Exception) with ruff B017

A bare pytest.raises(Exception) accepts whatever the body throws. The TypeError
a refactor introduces satisfies it exactly as well as the rejection the test was
written for, so the crash reads as a pass and the test never goes red.

All 111 existing sites are narrowed here. A runtime probe recorded the concrete
exception each one actually catches, and each site now names that type. Where
the code under test genuinely raises a bare Exception, the site pins a stable
slice of the message with match= instead.

Two sites tell on themselves. The shared responses-API cancel test raises
"custom_llm_provider is required but passed as None" rather than talking to a
provider at all, because cancel_responses takes a provider, not a model. And
test_bedrock_guardrails_with_streaming was the only test in its file still
passing without AWS credentials, because the NoCredentialsError boto3 raised
long before the guardrail ran satisfied the blind raises.

* fix(test): widen the openai batch-dispatch assertion to OpenAIError

The narrowed NotFoundError only holds where OPENAI_API_KEY is set. Without one
the SDK raises OpenAIError while building the client, long before any 404, so CI
went red. OpenAIError covers both and still rejects a TypeError from a refactor.
2026-08-20 18:09:42 -07:00
mateo-berri
6742637c95 docs(cognition): tick the responses column in the provider table
The support matrix says cognition serves /v1/responses, but the README row
left that column blank, so the two disagreed. Every other provider row tracks
the matrix, so bring this one in line.
2026-08-20 18:05:06 -07:00
mateo-berri
27c3f87aef fix(fal_ai): price gpt-image-2 per size and quality from request params 2026-08-20 18:00:27 -07:00
Mateo Wang
6eacdbfbf0
Merge pull request #37541 from ljogeiger/litellm_vertex_parallel_fc_thought_signatures
fix(vertex_ai): only fall back to a placeholder thought signature on the first parallel function call
2026-08-20 17:53:05 -07:00
devin-ai-integration[bot]
c74e9e75f9
feat(ui): support project input and output TPM limits (#37676)
The Model-Specific Limits rows now carry Input TPM and Output TPM, and a
limit the operator removes is sent as an explicitly empty map so
/project/update actually drops it instead of leaving the stored quota
enforced behind a UI that shows it gone.

Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-20 17:43:52 -07:00
mateo-berri
de7dcbbc67 Carry real cache counts up instead of zeroing them on partial rows
cache_read_input_tokens and cache_creation_input_tokens are pydantic extras
on Usage, not declared fields, so filling them in created keys that were not
there before rather than replacing a None. Readers that test for presence
then took the new zero as authoritative: the spend log writer skipped its
own copy from prompt_tokens_details, turning a real cache read of 500 into
0, and the prometheus provider cache counters stopped incrementing.

Carry the prompt_tokens_details counts up before defaulting to zero, so a
partial row reports the same cache numbers a complete one does. Renamed the
helper to say what it now does.
2026-08-20 17:41:03 -07:00
mateo-berri
1a9e9951e1 fix(cognition): restore Lightning SWE pricing and declare responses support
The swe-1.7 rates were briefly lowered to the standard tier. The docs page
records the API-served swe-1.7 as the Cerebras-served Lightning tier, so put
the matching rates back rather than have the cost map and the docs disagree.

Cognition also answers /v1/responses through the chat-completions bridge, the
same as every other provider in the JSON registry, so the endpoints support
matrix should say so instead of under-declaring it.
2026-08-20 17:39:29 -07:00
Mateo Wang
211b399761
Merge pull request #37658 from BerriAI/litellm_model_registry_consolidated_20260820
fix(model_prices): consolidate eleven open registry audits into one changeset
2026-08-20 17:39:19 -07:00
mateo-berri
16bba15434 require an incomplete reason before overriding finish_reason 2026-08-20 17:38:47 -07:00
mateo-berri
332a0f1b9b fix(cognition): price swe-1.7 from the published standard tier
The swe-1.7 rates were carried over from the closed prior attempt and
match SWE-1.7 Lightning, 5x the SWE-1.7 Max and Medium rates the vendor
publishes. swe-1.6 was already on the standard tier, so the two entries
disagreed with each other. Both now read 0.5 in, 2.5 out, 0.2 cached per
million tokens.

Also drops the redundant registry comment in constants.py.
2026-08-20 17:33:59 -07:00
mateo-berri
d924226b01 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_lit_5870_passthrough_e2e_pins_wt 2026-08-20 17:33:35 -07:00
mateo-berri
94239d281f test(e2e): name the pinned GitHub issue in each passthrough test docstring
The passthrough tests and their coverage registry rows pointed at the internal
ticket id, which does not resolve for anyone following a link from
status.litellm.ai. Each test docstring and registry rationale now names the
GitHub issue it pins: #36086 for the two prefix routing cases, #36087 for the
file list cursors, #36523 for streamed Responses cost, and #36646 for
embeddings spend.
2026-08-20 17:33:33 -07:00
Mateo Wang
02e67cd715
Merge pull request #35181 from BerriAI/litellm_block_unpriced_models
feat(proxy): add admin toggle to block requests for models without pricing
2026-08-20 17:32:28 -07:00
Yassin Kortam
66a89f5a6e
perf(reset_budget_job): elect one sweeper per tick and bound the window scan (#36497)
Every pod schedules the budget reset job, so a fleet re-read the whole due
population and wrote it back against one Postgres at the same calendar
boundary, multiplying a single sweep by its replica count. The job now takes
the shared PodLockManager lease, so one pod sweeps per tick. A deployment with
no Redis keeps its previous behavior, and a Redis that cannot answer sweeps
unguarded rather than stranding every expired budget at its cap.

The per-window scan read every row carrying budget_limits in one statement, so
its cost grew with the deployment's key count. It is now keyset-paginated and
walks to the end of the table on every sweep. A per-run cap would need a resume
position, and no pod can hold one because the lease rotates between ticks, so
the strictly advancing cursor is what terminates the walk.

Found and updated rows were also JSON-serialized into the service hook's
metadata and into debug lines on every chunk, on the event loop, whether or not
anything consumed them. The hooks now carry counts, and the debug payload is
deferred until a record is actually emitted.

Resolves LIT-4793

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-20 17:29:07 -07:00
yuneng-jiang
e98b9fda90
test: assert the prefixed model the responses bridge now hands back (#37744)
a369cb0da7 made the chat-to-responses bridge return the routing prefix on the
model it passes to responses(), so responses() re-resolving the provider is a
no-op instead of stripping a second prefix. It updated the bridge's own unit
tests but not this one, which still asserted the stripped id and has been
failing llm_translation_testing since that change landed.

The provider still receives gpt-5.4: responses() strips the openai/ prefix on
its own resolve, one layer later than this assertion used to sit. The stale
comment claiming the prefix is stripped before routing goes with it.
2026-08-21 00:27:32 +00:00
Mateo Wang
987478abe4
Merge pull request #37740 from BerriAI/litellm_redis_url_pool_credential_provider
fix(redis): apply Azure AD and GCP IAM auth to every async client path
2026-08-20 17:24:10 -07:00
devin-ai-integration[bot]
c008d5e2bd
fix(scim): propagate team roster write failures on group and user writes (#37700)
SCIM roster writes were swallowed, so a group or user push returned 200 while the
team roster never received the membership. Surfacing the failure fixes that, but
aborting on the first failed write leaves the rest of the batch unattempted on top
of unrolled-back, which is worse than what it replaces.

Every roster write in a reconciliation is now attempted, and the ones that did not
land are reported together, naming each failed add and remove. Rollback would be the
other option and it is not safe here: the compensating write can fail too, and it can
strip a membership that pre-dated the push. SCIM reconciliation is idempotent, so a
named partial failure is what the IdP's next push needs to close the gap.

The reported status still follows the failures, so a unanimous 404 stays a 404 and
only a batch whose failures disagree falls back to 500.

Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-20 17:23:39 -07:00
Mateo Wang
286c75f69d
Merge pull request #37729 from BerriAI/devin_ai_fal_gpt_image_2
feat(fal_ai): add gpt-image-2 image generation support
2026-08-20 17:23:24 -07:00
devin-ai-integration[bot]
43995bcb75
fix(db): apply the configured connection params to the read replica URL (#37691)
The read replica never received the operator's DB pool settings, so its
Prisma pool fell back to `num_physical_cpus * 2 + 1` and the configured cap
was not enforced. Both startup paths now pass the same params to the reader:
the CLI, and the componentized entrypoints that go through
`DatabaseURLSettings.apply_to_env`.

Only pool and timeout params are inherited, through a single allowlist both
paths share. Anything that decides which tables a query resolves against
stays on the writer, including entries smuggled in through
`database_extra_connection_params`, so a writer `search_path` cannot repoint
reader queries. Params the operator pinned on the replica URL still win.

Co-authored-by: Yassin Kortam <yassin.kortam@gmail.com>
Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-20 17:23:06 -07:00
Mateo Wang
fb3dd0fb98
Merge pull request #37722 from BerriAI/litellm_gpt56_max_input_tokens
fix(model-costs): correct gpt-5.6 max input tokens to 922k
2026-08-20 17:21:09 -07:00
mateo-berri
7b25ee13c9 fold the two reasoning-item casts into one shared helper 2026-08-20 17:17:48 -07:00
mateo-berri
e00301703f feat(cognition): give Cognition its own provider identity
Cognition serves an OpenAI-compatible /v1/chat/completions endpoint, so it has been onboarded as
custom_llm_provider: openai. That books its traffic as OpenAI, which means OpenAI-specific cost
discounts and provider-level reporting apply to it.

Registers cognition through the JSON provider registry: a providers.json entry with
COGNITION_API_KEY and COGNITION_API_BASE, LlmProviders.COGNITION, the constants.py provider lists,
cost map entries for swe-1.6 and swe-1.7, the provider endpoints matrix, the dashboard provider
fields, and tests. JSON providers can now also be resolved from their base url alone, so an
api_base pointing at a known provider no longer falls through to an unresolved provider.
2026-08-20 17:16:53 -07:00
yuneng-jiang
cc812cdfc7
test: point the live web search, groq and vertex image suites at models that still exist (#37733)
* test: point the live web search, groq and vertex image suites at models that still exist

Three CircleCI jobs on the staging-to-main promotion are red because the models
their live suites call have been retired by the providers, not because anything
in litellm changed.

openai/gpt-4o-search-preview now answers "has been deprecated" (its dated id
gpt-4o-search-preview-2025-03-11 carries deprecation_date 2026-07-23), so the
two web search conformance tests and the web search cost tracking test move to
gpt-5-search-api, the current search model. It keeps mode chat,
supports_web_search and a search_context_cost_per_query map, so the cost
assertion still resolves.

groq/llama-3.1-8b-instant reached its deprecation_date of 2026-08-16 and Groq
answers "does not exist or you do not have access to it". It follows
groq/llama-3.3-70b-versatile to groq/openai/gpt-oss-120b, the same replacement
PR #37422 already picked. The proxy config that job boots routes on a */*
wildcard, so no config change is needed.

vertex_ai/imagen-3.0-fast-generate-001 404s with "was not found or your project
does not have access to it". Google retired the whole Imagen family across
Vertex and the Gemini API, so there is no Imagen id left to point at. The class
is removed rather than repointed: Vertex image generation is already covered
live by TestVertexAIGeminiImageGeneration on vertex_ai/gemini-2.5-flash-image,
and the Imagen request and response transformations keep their offline coverage
in tests/test_litellm/llms/vertex_ai/image_generation/.

Only live call sites move. Remaining references to the old ids sit in offline
cost-map and transformation tests, where the string is a lookup key and no
request leaves the process.

* chore(lint): ratchet the TQ005 ceiling down to the count this branch reached

Removing the retired TestVertexImageGeneration class cleared one TQ005
violation, so the gate demands the limit come down with it.

make lint-budget-update only lowers a limit by the delta a branch cleared, and
this ceiling already sat 2 above the base count, so the tool landed on 2834
while the gate wants the limit at or below the 2832 this branch reached. The
remaining 2 are that stale headroom, which is exactly what the gate is asking
to reclaim.
2026-08-20 17:03:35 -07:00
mateo-berri
6d66567915 fix(fal_ai): stop advertising /v1/images/edits for gpt-image-2 edit
The edit model is reached through the image generation path with fal's
image_urls param; /v1/images/edits is not wired for fal_ai and errors.
Point supported_endpoints at /v1/images/generations and say so in the
entry notes.
2026-08-20 17:02:07 -07:00