-
-
Notifications
You must be signed in to change notification settings - Fork 11k
feat(proxy): type Customer Management response_model for OpenAPI coverage #31043
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
ryan-crabbe-berri
merged 13 commits into
litellm_internal_staging
from
litellm_customer_response_models
Jun 30, 2026
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
d857b1c
feat(proxy): type Customer Management response_model for OpenAPI cove…
ryan-crabbe-berri f6eb184
fix(proxy): keep budget_id in typed customer responses
ryan-crabbe-berri fc41235
fix(proxy): keep nested budget fields in customer responses
ryan-crabbe-berri 38e6d11
test(proxy): add golden-master characterization tests for customer re…
ryan-crabbe-berri 490000e
refactor(proxy): make the customer response flow type-safe
ryan-crabbe-berri 8af41f5
refactor(proxy): annotate customer response mapper param as BaseModel
ryan-crabbe-berri 8bd32d7
Merge remote-tracking branch 'origin/litellm_internal_staging' into l…
ryan-crabbe-berri e5660c1
style(test): ruff format customer endpoint tests
ryan-crabbe-berri df01ad6
Merge remote-tracking branch 'origin/litellm_internal_staging' into l…
ryan-crabbe-berri 99f17cb
test(proxy): give customer budget test update mocks a valid model_dump
ryan-crabbe-berri 0ab1e8b
Merge remote-tracking branch 'origin/litellm_internal_staging' into l…
ryan-crabbe-berri 99c7ca7
chore(ui): regenerate API types from proxy OpenAPI spec
ryan-crabbe-berri 159a29f
fix(ui): make generated API types stable across Python versions
ryan-crabbe-berri File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
litellm/types/proxy/management_endpoints/customer_endpoints.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| from typing import List, Optional | ||
|
|
||
| from pydantic import BaseModel, Field | ||
|
|
||
| from litellm.models.budget import LiteLLM_BudgetTableFull | ||
| from litellm.models.end_user import LiteLLM_EndUserTable | ||
|
|
||
|
|
||
| class CustomerResponse(LiteLLM_EndUserTable): | ||
| """Customer object returned by the /customer read+write endpoints. | ||
|
|
||
| Nests the full budget response model so server-managed budget fields | ||
| (budget_reset_at, created_at) survive response_model filtering, rather than | ||
| the narrow write-allowlist shape LiteLLM_EndUserTable carries for internal use. | ||
| """ | ||
|
|
||
| litellm_budget_table: Optional[LiteLLM_BudgetTableFull] = None # pyright: ignore | ||
|
|
||
|
|
||
| class BlockUsersResponse(BaseModel): | ||
| blocked_users: List[LiteLLM_EndUserTable] | ||
|
|
||
|
|
||
| class UnblockUsersResponse(BaseModel): | ||
| blocked_users: List[str] = Field(description="User IDs that remain blocked after this unblock call") | ||
|
|
||
|
greptile-apps[bot] marked this conversation as resolved.
|
||
|
|
||
| class DeleteCustomersResponse(BaseModel): | ||
| deleted_customers: int | ||
| message: str | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CustomerResponsenow validates every customer row's nested budget asLiteLLM_BudgetTableFull, but that model requirescreated_at. When_to_customer_response()receives a customer row whose joined budget payload lackscreated_at, the customer endpoints can fail response validation and return a 500. This can happen with partial joined budget rows or existing callers/tests that previously used the narrowerLiteLLM_BudgetTableshape, which did not requirecreated_at.Artifacts
Repro: focused mapper and endpoint harness source
Repro: direct validation error and HTTP 500 Internal Server Error output
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile's repro fabricates a budget object with no created_at and feeds it straight to the internal mapper, but no real /customer/* request can reach that state since the budget is always None or a DB row whose created_at is NOT NULL DEFAULT now()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair point —
litellm_budgettable.created_atisNOT NULL DEFAULT now(), so any real DB row returned from a/customer/*handler will always carry it. The concern only applies to hand-crafted test stubs that omitcreated_at, which isn't a production failure path. I'll withdraw this comment.