Commit graph

44458 commits

Author SHA1 Message Date
mateo-berri
a1f1aa9cb5 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_harden_retry_breadcrumb_credentials 2026-08-24 12:57:42 -07:00
mateo-berri
721227e9ee refactor(router): scrub retry-breadcrumb credentials by pattern, not a denylist
Enumerating credential-bearing kwargs in RETRY_BREADCRUMB_EXCLUDED_KWARGS is always one
new kwarg behind: it missed top-level extra_headers and provider token fields, which
log_retry still copied into router.previous_models verbatim. Scrub the breadcrumb with
mask_credentials_in_payload instead, so credential-named values are masked at any depth
(extra_headers.authorization, api_key, aws_secret_access_key, vertex_credentials,
azure_ad_token, and future kwargs), and leave the exclusion set to the request payload and
router walk state only.

This hardens the in-memory breadcrumb; it is not a fix for a reproduced SpendLogs leak. The
SpendLogs metadata allowlist and the universal previous_models stripping already keep this
breadcrumb off every persisted surface.

Parametrize the regression test over provider_specific_header, extra_headers, and api_key,
asserting the raw credential value never survives into previous_models for any shape while
the container key still reaches the breadcrumb
2026-08-24 12:57:32 -07:00
Mateo Wang
d0da90ee6d
Merge pull request #38115 from BerriAI/litellm_fix_runwayml_video_provider
fix(runwayml): route every generation endpoint and fix video cost tracking
2026-08-24 12:35:59 -07:00
mateo-berri
1c18d3eda3 fix(router): stop copying forwarded credentials into retry breadcrumbs
log_retry copied every kwarg into the previous_models breadcrumb, so a client's
forwarded Authorization (provider_specific_header) and the deployment api_key /
headers rode along in an in-memory structure whose comment says it reaches spend
logs and logging callbacks. Those values have no diagnostic use in a breadcrumb.

Add provider_specific_header, headers, and api_key to RETRY_BREADCRUMB_EXCLUDED_KWARGS
so the credential is never placed there in the first place. This is defense in depth:
no persisted leak exists today, since the SpendLogs metadata allowlist and every
logging integration already drop previous_models before serialization. Removing the
credential at the source means a future logging path cannot expose it either
2026-08-24 12:34:27 -07:00
Mateo Wang
09f4096641
Merge pull request #38101 from BerriAI/litellm_health_test_connection_health_check_params
fix(health): apply model_info.health_check_params to health check probes
2026-08-24 12:34:13 -07:00
ryan-crabbe-berri
776b585f70
Merge pull request #37908 from BerriAI/litellm_ruff_dead_test_code
fix(proxy): keep every value of a repeated form key, and gate the tests that hid it
2026-08-24 12:31:55 -07:00
ryan-crabbe-berri
fdae9306d8
Merge pull request #38130 from BerriAI/litellm_missing_raise_anthropic_import
fix(utils): make prompt_token_calculator count claude models again
2026-08-24 12:26:02 -07:00
mateo-berri
3030e974b8 fix(runwayml): skip progress scaling when Runway returns a null progress 2026-08-24 12:20:00 -07:00
Mateo Wang
37b659e864
Merge pull request #38108 from BerriAI/litellm_fix_46_thinking_budget
fix(anthropic): keep legacy thinking budget_tokens on Claude 4.6 models on /v1/messages
2026-08-24 12:19:37 -07:00
ryan-crabbe-berri
6975b8ea4b fix(utils): make prompt_token_calculator count claude models again
The claude branch called the anthropic SDK's `Anthropic().count_tokens`, which the
SDK removed, so every claude call raised AttributeError. Counting now goes through
litellm's own token_counter, which handles anthropic models offline and drops the
SDK dependency entirely.

Hiding that was a swallowed error: `except Exception: Exception("Anthropic import
failed please run `pip install anthropic`")` built the exception without raising
it, so an environment missing the SDK fell through to the unguarded
`from anthropic import ...` on the next line and got a bare ModuleNotFoundError
instead of the install hint.

That was the codebase's last PLW0133, so the rule graduates from the ratcheted
budget into ruff.toml where it hard-fails, and editors get the diagnostic inline.
2026-08-24 12:19:03 -07:00
Mateo Wang
f818a48ae5
Merge pull request #36513 from Souravrajvi0/bugfix/video-edits-form-body-36487-8fc4
fix(proxy): parse form-encoded video edit/extension bodies after auth
2026-08-24 12:03:10 -07:00
mateo-berri
458a63935f test(health): guard that test_connection authorizes on post-merge probe params
Add an endpoint-level regression test asserting can_user_make_model_call
receives the litellm_params after health_check_params are merged in, so the
merge-before-auth ordering cannot silently regress and let a request smuggle
a field past authorization.
2026-08-24 11:58:33 -07:00
devin-ai-integration[bot]
a1134755ca
fix(ui): boot the UI image as an arbitrary uid by anchoring nginx writes under /tmp (#37982)
* fix(ui): boot the UI image as an arbitrary uid by anchoring nginx writes under /tmp

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(ui): type the arbitrary-uid image test fixture

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-24 11:57:36 -07:00
Mateo Wang
33c51e84b0
Merge pull request #35415 from BerriAI/litellm_azure_ai_entra_auth
feat(azure_ai): support entra id / oauth auth on every azure ai foundry route
2026-08-24 11:54:48 -07:00
mateo-berri
25b379f3c7 test: register supports_legacy_thinking in model-prices schema
Regenerate model_prices_and_context_window.schema.json and add the flag to
the inline validator schema in test_utils.py so the new cost-map key passes
validate-model-prices-json and the JSON-valid test.
2026-08-24 11:47:21 -07:00
Darien Kindlund
b36f34813a
fix(anthropic): reconcile enum with declared type in output_format schema (#37882)
* fix(anthropic): reconcile enum with declared type in output_format schema

Anthropic cross-validates `enum` against `type` in structured outputs: every
enum value must match a single declared type. A union `type` array, or an enum
value whose JSON type differs from a scalar `type`, is rejected with
"Invalid schema: Enum value 'low' does not match declared type '['string','null']'"

filter_anthropic_output_schema had no enum/type reconciliation, so both keys
reached Anthropic untouched. Drop the conflicting `type` -- `enum` is the
tighter constraint, and an enum with no `type` is accepted

The drop is conditional: `type` is only removed when it is a union array, or
when some enum value does not match the scalar type. A matching enum plus
scalar `type` is left exactly as-is, so existing behaviour is unchanged

Pydantic emits the failing shape for Optional[SomeEnum], so this affects any
caller with a nullable enum field on the native output_format path. vertex_ai
is unaffected because it is forced onto the permissive tool-use path

Fixes #37881

* refactor(anthropic): make enum/type reconciliation immutable and precisely typed

Address review: the predicate registry was a mutable `dict[str, Any]`, and the
reconciliation removed `type` by mutating the built result with `pop`

- registry is now `Final[Mapping[str, Callable[[Any], bool]]]` wrapped in
  `MappingProxyType`, so predicate signatures are statically checked and the
  table cannot be mutated
- the conflict decision moves into a pure helper evaluated once against the
  input schema, and the conflicting `type` key is skipped at build time in the
  existing loop instead of being popped afterwards, so nothing is mutated

Behaviour is unchanged; all 27 tests in the schema-filter suite still pass
2026-08-24 11:43:47 -07:00
mateo-berri
b117190b0b chore(pricing): regenerate model prices schema for new video cost tier fields 2026-08-24 11:43:40 -07:00
Mateo Wang
a626170c89
Merge pull request #36806 from BerriAI/litellm_bedrock_converse_no_trailing_empty_chunk
fix(bedrock): stop emitting an empty assistant delta after the finish_reason chunk
2026-08-24 11:37:04 -07:00
mateo-berri
37f8b9600a Merge origin/litellm_internal_staging into litellm_azure_ai_entra_auth
Bring the Entra ID / OAuth auth work for Azure AI Foundry routes up to date
with staging and fix the lint-budget regressions the merge surfaced:

- widen get_azure_ai_auth_headers return type to Mapping[str, str] (LIT001)
- build the azure_ai image_generation request headers into a new Final local
  instead of rebinding the Final headers dict (reportGeneralTypeIssues)
- order HuggingFace rerank validate_environment params to match BaseRerankConfig
  so litellm_params lines up positionally (reportIncompatibleMethodOverride)
- add a match= to the credential-error test and document the handler-boundary
  patches the auth wiring tests rely on
2026-08-24 11:33:18 -07:00
mateo-berri
a7cd2cd439 Merge branch 'litellm_internal_staging' into litellm_fix_46_thinking_budget 2026-08-24 11:31:10 -07:00
mateo-berri
531aafdf75 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_health_test_connection_health_check_params
# Conflicts:
#	tests/test_litellm/proxy/test_health_check_max_tokens.py
2026-08-24 11:30:04 -07:00
mateo-berri
603d3358d6 Merge origin/litellm_internal_staging into bugfix/video-edits-form-body-36487-8fc4
Pulls in the detect-changes CI action and the test-unit job timeout bump, which clears the red lint and code-quality checks on this PR

The merged, tightened lint budgets flag this PR's own code, so this merge also makes video_reference_to_id a pure function instead of a helper that mutates its input dict, and rewrites the form-body regression test to call the video_edit and video_extension handlers directly rather than patching an internal class method. Adds pure-logic unit tests for video_reference_to_id
2026-08-24 11:26:03 -07:00
mateo-berri
bf4069a80c fix(proxy): authorize health test-connection on final probe params
Move _update_litellm_params_for_health_check before can_user_make_model_call
so health_check_params cannot retarget the probe after the auth check. Type
the Pegasus test helper signature and drop the redundant test narrative.
2026-08-24 11:24:21 -07:00
mateo-berri
6407a66375 fix(runwayml): route every generation endpoint and fix video cost tracking
Six defects in the RunwayML video provider:

- transform_video_create_request hardcoded /image_to_video, so text-to-video 400'd and video-to-video was unreachable; the endpoint is now selected from the inputs present (promptVideo/videoUri, promptImage, or text only)
- get_error_class raised instead of returning, turning a provider 4xx into a proxy 500 APIConnectionError; it now returns a RunwayMLError
- VideoObject.progress was typed int while Runway sends a 0..1 float, 500'ing status polls while RUNNING; it is now scaled to a 0..100 percent
- custom per-deployment pricing stored under litellm_metadata was ignored for video; the deployment model_info lookup now checks both metadata keys
- stale cost-map entries (gen3a_turbo, gen4_aleph) were removed and current models added, with output_cost_per_second_480p/_4k tier keys plumbed through the model-info and router types
- video cost now falls back to Runway's estimatedCost from the create response when no custom pricing is configured, and custom pricing always wins over it

Fixes #36483
2026-08-24 11:23:03 -07:00
Mateo Wang
9bcc00b1f1
Merge pull request #33310 from BerriAI/litellm_google_interactions_cost
fix(interactions): track cost and spend for Google Interactions API requests
2026-08-24 11:18:58 -07:00
Mateo Wang
10b42a84e6
Merge pull request #37917 from BerriAI/litellm_a2a_protocol_binding_casing
fix(a2a): normalize agent card protocolBinding casing before transport match
2026-08-24 11:14:01 -07:00
mateo-berri
fef5f41985 fix(anthropic): keep legacy thinking budget_tokens on Claude 4.6 models 2026-08-24 11:12:54 -07:00
mateo-berri
d0dd24ed6d fix(health): apply model_info.health_check_params to health check probes 2026-08-24 11:01:34 -07:00
Mateo Wang
ddf4c8e58b
Merge pull request #37953 from BerriAI/litellm_fix_24985_thinking_roundtrip
fix(anthropic): round-trip thinking blocks to OpenAI backends on /v1/messages
2026-08-24 10:57:23 -07:00
mateo-berri
fe567bd846 fix(a2a): speak the 0.3 dialect to servers with mis-cased protocol bindings 2026-08-24 10:51:14 -07:00
mateo-berri
91b2a9c360 fix(proxy): keep video reference normalization within lint budgets 2026-08-24 10:40:44 -07:00
mateo-berri
e0511e9384 Merge branch 'litellm_internal_staging' into litellm_bedrock_converse_no_trailing_empty_chunk
Resolves the test-file conflict by keeping both sides, extends the
finish-reason gate to trace-bearing metadata events so guardrail trace
chunks keep their pre-regression delta shape, parametrizes the
regression test over tool-call, mixed, and reasoning streams, and
repairs the one ant-design icon usage the lucide-react migration left
behind in skill_detail.tsx (semantic conflict on the base branch)
2026-08-24 10:37:32 -07:00
Mateo Wang
3122600e21
Merge pull request #37975 from BerriAI/litellm_databricks_cache_token_pricing
fix(databricks): bill cached tokens at cache rates and add missing Claude pricing
2026-08-24 10:36:19 -07:00
Mateo Wang
28b433a007
Merge pull request #37966 from BerriAI/litellm_1787426863_strategy_router_health_check
fix(proxy): skip health checks for strategy routers
2026-08-24 10:26:09 -07:00
ryan-crabbe-berri
4913b2a3ca
Merge pull request #33514 from ozolam/litellm_fix_skills_marketplace_commands_v2
fix(UI): correct skill install command and marketplace setup UX
2026-08-24 10:17:25 -07:00
yuneng-jiang
3fb1009f81
fix(ui): make playground chat bubbles theme-aware (#37978)
The playground message bubble painted its fill, border and avatar circle from
inline hex values, so in dark mode both bubbles stayed near-white while the text
inherited the dark foreground: the message body was unreadable. The MCP-events
placeholder bubble in ChatUI carried the same three fills.

They move onto the tokens the rest of the sweep already uses, so the assistant
surface is bg-card over border-border and the user surface is the info tint at
the same weight the other selected-state surfaces take. Light mode keeps the
same colour family it had.

The regression test asserts the token classes and that no inline style survives
on either surface, which is the exact shape the bug took.
2026-08-24 10:13:24 -07:00
yuneng-jiang
7113685a76
fix(ui): repoint the key detail URL to the rotated hash after regenerating (#37968)
Regenerating a key from the key info page left the ?key= query param on the
old hash, so dismissing the dialog or reloading landed on a key that no longer
exists and the page rendered "Key not found".

Two defects had to line up. POST /key/{key}/regenerate returns the rotated
hash in token_id and leaves token null, but RegenerateKeyModal read
response.token || response.key_id, neither of which the endpoint populates, so
it always reported the old hash back to its parent. And KeyInfoView's
onKeyDataUpdate prop had no caller anywhere in the tree: VirtualKeysTable owns
the ?key= param and mounts the view but never passed it, so even a correct
hash went nowhere.

VirtualKeysTable now handles the update by pointing ?key= at the rotated hash
and refetching. KeyInfoView holds that callback until the regenerate dialog is
dismissed rather than firing it on the API response, because swapping the
selected key mid-dialog unmounts the view and tears down the one-time
plaintext key before the user can copy it.
2026-08-24 10:12:55 -07:00
yuneng-jiang
5b1c142c6e
fix(ui): render team and org tpm/rpm limits of 0 as 0 instead of Unlimited (#37916)
* fix(ui): render team and org tpm/rpm limits of 0 as 0 instead of Unlimited

A tpm_limit or rpm_limit of 0 is a hard block on the backend (every request 429s) and only null means unlimited, but the team and organization views rendered both as "Unlimited" (and a team-member limit of 0 as "No Limit") because every display site used a falsy || fallback. The team member edit dialog also seeded its form with `tpm_limit || null`, so opening Edit Member on a member stored with 0 and clicking Save sent null to /team/member_update and silently turned the hard block into unlimited

Every limit display site in TeamInfo, organization_view, the organizations list cell and the team members table now uses a nullish check, and both member form seeding paths keep 0 for max_budget_in_team, tpm_limit and rpm_limit. Regression tests cover each site and the existing memberFormValues test that asserted 0 -> null is flipped to assert 0 survives

Resolves LIT-5760

* test(ui): assert a stored 0 member limit survives an untouched save

The EditMembership integration test named the old 0 -> null collapse as the expected payload, so the related-tests CI job went red once the form kept 0. It now asserts 0 survives and only the empty budget_duration collapses to null. The TeamMemberTab fixture is built with a map instead of mutating the nested membership
2026-08-24 10:12:52 -07:00
yuneng-jiang
6db5a5d660
fix(ui): restore the public model name tooltip layout in the add model flow (#37986)
The tooltip popup is an inline-flex row, so the four sibling blocks passed as a fragment laid out side by side in four columns. Wrap them in a single flex-col container instead.

The inline code samples also used bg-muted, which is defined against the page surface, not the inverted tooltip surface, so they rendered as near-white chips carrying near-white text. Tint them from the popup's own token instead.
2026-08-24 10:12:46 -07:00
yuneng-jiang
5f56be3294
fix(ui): theme the created-key box so it follows dark mode (#37985)
The virtual key shown after creating a key sits in a div with a
hardcoded #f8f8f8 inline background, so in dark mode the box keeps
the light background while the key text inherits the light foreground
color, leaving the key nearly unreadable. Swap the inline styles for
the bg-muted and text-foreground tokens, which resolve per theme.
2026-08-24 10:12:16 -07:00
yuneng-jiang
a72203eae4
fix(terraform): add soft_budget, tags, and soft_budget_alerting_emails to litellm_team (#37918)
* fix(terraform): add soft_budget, tags, and soft_budget_alerting_emails to litellm_team

The team resource rejected soft_budget and tags at plan time and had no way
to express the list-valued metadata.soft_budget_alerting_emails the proxy
reads for soft-budget alerts, even though /team/new and /team/update accept
all three. Add the attributes, forward them in buildTeamData (alert emails
merged under metadata, where the proxy stores them), and send the full
metadata map whenever either half changes because /team/update replaces
metadata wholesale.

Read was decoding /team/info as if the team fields were top-level, but the
proxy nests them under team_info, so every attribute silently fell back to
prior state. Decode the envelope and split the proxy's metadata back into
tags / soft_budget_alerting_emails / string metadata, dropping the
server-managed team_member_budget_id.

Verified with OpenTofu plan/apply against a live proxy: the attributes are
accepted, land on the proxy, refresh into state, re-plan clean, propagate
on update, and clear when removed from HCL.

* fix(terraform): clear litellm_team.soft_budget in state when the proxy returns null

Read only wrote soft_budget when the proxy returned a value, so a soft
budget cleared outside Terraform stayed in state and never surfaced as
drift. Set it from the response unconditionally so a null clears it.
2026-08-24 10:12:10 -07:00
ryan-crabbe-berri
7d5a2c1a0d Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_ruff_dead_test_code
# Conflicts:
#	ruff-tests.toml
2026-08-24 09:46:56 -07:00
ryan-crabbe-berri
ee935cec23 refactor(proxy): trim the multi_items comment to the non-obvious clause 2026-08-24 09:46:35 -07:00
yuneng-jiang
f005afa146
test(exception-mapping): pin the status and error-shape table every provider maps to (#37807)
Some checks are pending
Postgres Tests / proxy-behavior (push) Waiting to run
Unit Tests: Documentation Validation / documentation (push) Waiting to run
Unit Tests: Proxy DB Operations / assert-shard-coverage (push) Waiting to run
Unit Tests: Proxy DB Operations / auth-checks (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / budgets (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / custom-logging (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / db-and-spend (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / endpoints-and-responses (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / guardrails-hooks (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / jwt-and-keys (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / key-generation (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / logging-misc (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-runtime (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-server-core (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-utils (push) Blocked by required conditions
Unit Tests / All Other Providers (push) Waiting to run
Unit Tests / Vertex AI (push) Waiting to run
Unit Tests / misc (push) Waiting to run
Unit Tests / proxy-auth (push) Waiting to run
Unit Tests / proxy-endpoints (push) Waiting to run
Unit Tests / proxy-extras (push) Waiting to run
Unit Tests / caching-local (push) Waiting to run
Unit Tests / core-utils (push) Waiting to run
Unit Tests / proxy-infra (push) Waiting to run
Unit Tests / enterprise-package (push) Waiting to run
Unit Tests / enterprise-routing (push) Waiting to run
Unit Tests / integrations (push) Waiting to run
Unit Tests / proxy-server (push) Waiting to run
Unit Tests / responses-caching-types (push) Waiting to run
GitHub Actions Security Analysis / zizmor (push) Waiting to run
`exception_type` decides the class and status a caller sees for every provider
failure, across 190 raise sites, and the tests for it were written one incident
at a time. Nothing said what a plain 401 from any given provider should be, so
mutating a raise site went unnoticed: swapping the class at each of the 190 in
turn, the mapped test file caught 15.

Adds two tables asserted end to end through `exception_type`: 25 providers by
the 9 upstream statuses, and the three error shapes the router branches on
(a full context window, a content policy block, a timeout). The same 190
mutants now fail 97 of them.

The tables record today's behavior, uneven where it is uneven. cloudflare,
ollama and vllm map no status at all, so every failure reaches the caller as a
500. A full context window is recognised by 15 of the 25, and a content policy
block by 11, which bounds where `context_window_fallbacks` and the content
policy retry policy can fire.
2026-08-22 22:59:02 -07:00
yuneng-jiang
d1f3778849
perf(ci): give the two longest unit shards the runner's spare cores (#37804)
proxy-endpoints and proxy-infra are the unit tier's critical path at 358s and
325s of pytest, measured on staging 2026-08-21, and both run two xdist workers
on a four-vCPU runner. proxy-server already runs four. This is the cheaper half
of splitting them: no second job, so no second setup to pay for.
2026-08-22 22:58:26 -07:00
yuneng-jiang
68489f62ff
ci: run the enterprise package suite in GitHub Actions (#37798)
tests/enterprise is 13 files and 244 tests that only CircleCI runs, and CircleCI
gates nothing: it triggers on PR labeled events, none of its jobs are required,
and red runs get merged past. So the suite that covers the enterprise package's
guardrails, auth and management endpoints has had no say in whether a change
lands.

Measured on 2026-08-21 with every credential stripped from the environment: 240
passed, 4 skipped, nothing failed. It needs no provider key, so it can be a
required shard rather than a scheduled lane, unlike the other CircleCI suites in
this group, which each carry a live-API minority.

The CircleCI job is removed in the same commit so the suite runs once, not twice.
2026-08-22 22:57:50 -07:00
yuneng-jiang
ae0e8a20db
fix(ci): run the migration DDL guard, and stop it reading comments as SQL (#37791)
* fix(ci): make the migration DDL guard run, and stop it reading comments as SQL

TestMigrationSQLIdempotency requires guarded DDL across litellm-proxy-extras
and has never run in any job, so the convention eroded quietly. Four of its
assertions fail today, and it was allowlisted rather than wired up because
fixing the migrations is not an option: Prisma checksums an applied migration,
so editing one breaks `migrate deploy` for every existing install.

Two things were wrong with the guard itself. It scanned raw lines, so Prisma's
own `-- CREATE INDEX CONCURRENTLY ...` explanations counted as the statements
they describe, which is two of the reported migrations. And it had no way to
say "these predate the rule", so the only options were editing immutable files
or leaving the whole file unrun.

Comments are now stripped before matching, on the drop-column rule too, and the
migrations that already violate are named once in _PRE_GUARD_MIGRATIONS. The
rules bind everything after them, so a new migration with bare CREATE TABLE,
ADD COLUMN, CREATE INDEX or an unguarded ADD CONSTRAINT now fails a check
instead of landing unnoticed.

That set is 14 migrations, not the 13 previously recorded, measured after
comment-stripping. It can only shrink: a test fails if an entry names no
migration on disk, and another fails if an entry no longer violates anything.

The file now runs as a proxy-extras shard and comes off the coverage allowlist.

* fix(ci): strip block comments in the migration guard too

Prisma opens a destructive migration with a /* Warnings: You are about to
drop the column ... */ header. Nothing in the tree trips a rule on that text
today, but it is prose about a statement rather than the statement, and the
line-comment fix left the class open. Bodies are blanked rather than removed
so the reported line number still points at the real statement.
2026-08-22 22:57:16 -07:00
yuneng-jiang
b31484ed19
ci: run the keyless caching tests that ran in no job (#37790)
The allowlist recorded eight files in tests/local_testing, 118 tests, that
every job globbing that directory then deselects: local_testing_part1 and
part2 carry `-k "... and not caching and not cache"`, and the other three keep
one unrelated keyword each. They counted as covered while running nowhere.

Five of the eight need nothing. Measured with no provider credentials and no
Redis: test_cache_preset_key, test_caching_handler, test_prompt_caching,
test_responses_stream_cache_keys and test_unit_test_caching pass, 45 tests
together, and they now run as a caching-local shard. The other three stay
allowlisted with what they actually need recorded rather than a question:
test_caching wants Redis and a provider key for 37 of its 65, disk-cache wants
OPENAI_API_KEY for 2 of 4, gcs-cache wants GCS credentials for all 4.

Taking them off the allowlist exposed a gap in the slice guard itself: it
reasoned only about CircleCI `-k` expressions, so a file every slice drops read
as unrun even when a workflow names it outright. It now credits workflow
test-paths the way the census already does, and only workflows, so a tree only
CircleCI globs is still reported.
2026-08-22 22:56:43 -07:00
yuneng-jiang
6c30b4331d
ci: measure enterprise/ coverage (#37788)
codecov.yaml has carried an `Enterprise` component scoped to `enterprise/**`
since it was written, and it has never received a line of data. Every one of
the 19 coverage invocations across the unit base, the MCP workflow and the
CircleCI config passes `--cov=./litellm` and nothing else, so 11,203 lines of
paid-customer code sat outside the measured universe while the reported number
described only the rest.

litellm-enterprise is a uv workspace member and a direct dependency, so every
job that syncs already has it installed and importable; only the measurement
was missing.

Measured on tests/test_litellm/enterprise, the shard that exercises this code:
0 enterprise files in the report before, 142 after, at `enterprise/...` paths
that match the component's existing glob. That shard alone puts enterprise at
30.8%, which nudged its own total from 24.09% to 24.20% rather than down. The
aggregate direction across every shard is not knowable until they all report,
and a drop there is the instrument working, not a regression.
2026-08-22 22:55:01 -07:00
yuneng-jiang
a734afca32
feat(ci): gate patching of SDK internals in tests as TQ008 (#37787)
* feat(ci): gate patching of SDK internals in tests as TQ008

TQ002 catches the narrowest symptom of the suite's dominant mocking idiom,
patch X then assert only that X was called. The idiom itself is wider: tests
reach for litellm's own functions instead of faking the wire, so they pin how
the code is wired rather than what it does, and a test that patches internals
but makes weak real assertions trips nothing today.

TQ008 counts patch targets rooted at `litellm`, both the dotted string form and
the attribute chain handed to patch.object, and ratchets like every other rule.
Mocking anything outside the SDK is untouched: respx, httpx transports and
third-party clients do not trip it, which is the point, since those are the
patterns this is meant to move the suite toward.

Seeded at 9,643, in line with the ~9.4k patch sites an independent grep found
in the mirror. The burn-down horizon is long; the value here is stopping the
flow rather than clearing the stock.

Five existing rule tests patched `litellm.completion` incidentally and now
report TQ008 alongside what they were pinning. Their expected values are
updated to the accurate pair rather than loosened, so they keep failing on a
regression in either rule.

* test: add TQ008 to the shipped-budget rule canary

* fix(ci): resolve imported SDK names in TQ008

patch.object(handler.OpenAIChatCompletion, ...) after a from-import reaches the
same internal as the dotted string form, but the rule only saw the bare local
name and let it through. Import bindings are now resolved to the path they
stand for, so the aliased, renamed and from-imported forms all read alike and
the reported target is the real one.

That is 1,496 patches the ratchet could not see, so the TQ008 limit moves from
9,643 to 11,139. Third-party names and locals with no SDK import behind them
stay unflagged.
2026-08-22 22:54:30 -07:00