Fix credit model: allowance is a floor, credits add on top (max_budget = allowance + credits, not reduced by cycle overspend)

This commit is contained in:
inference-bot committed 2026-10-03 13:06:02 -06:00
1 parent 563881d63c
commit 052a109040
1 file changed
+10 -14
+10 -14
View File
@@ -584,32 +584,28 @@ def add_credits(email: str, delta: float, reason: str, reference: str | None = N
def compute_max_budget(allowance: float, credit_balance: float, team_spend: float | None) -> dict:
"""Compute the effective LiteLLM max_budget from the two buckets.
Model: the member has a monthly ALLOWANCE (resets via LiteLLM's
budget_duration) plus a NON-EXPIRING credit balance. Spend draws the
allowance first; once spend exceeds the allowance within a cycle, credits
cover the overflow.
Model: the member has a monthly ALLOWANCE (renews on each membership
payment) plus a credit balance that adds spendable headroom ON TOP of the
allowance. The total spendable cap is simply `allowance + credit_balance`
— credits never shrink the allowance; they extend it.
`team_spend` is the member's spend so far this cycle (from LiteLLM).
Credits already consumed this cycle are excluded from the available pool
so the pushed max_budget reflects exactly what's left:
max_budget = allowance + credits_remaining
`team_spend` is the member's spend so far this cycle (from LiteLLM). It is
used only to split the spend between allowance vs credits for display, NOT
to reduce the cap.
Returns {"max_budget", "allowance_used", "credits_used"} for dashboards.
"""
max_budget = allowance + credit_balance
if team_spend is None:
# Unknown spend: be permissive (full allowance + full credits) so we
# never wrongly block a member over a metrics gap.
return {
"max_budget": allowance + credit_balance,
"max_budget": max_budget,
"allowance_used": 0.0,
"credits_used": 0.0,
}
allowance_used = min(max(team_spend, 0.0), allowance)
credits_used = max(0.0, team_spend - allowance)
credits_remaining = max(0.0, credit_balance - credits_used)
return {
"max_budget": allowance + credits_remaining,
"max_budget": max_budget,
"allowance_used": allowance_used,
"credits_used": credits_used,
}