( limits: ClaudeAILimits, model: string, )
| 43 | * Returns null if no message should be shown |
| 44 | */ |
| 45 | export function getRateLimitMessage( |
| 46 | limits: ClaudeAILimits, |
| 47 | model: string, |
| 48 | ): RateLimitMessage | null { |
| 49 | // Check overage scenarios first (when subscription is rejected but overage is available) |
| 50 | // getUsingOverageText is rendered separately from warning. |
| 51 | if (limits.isUsingOverage) { |
| 52 | // Show warning if approaching overage spending limit |
| 53 | if (limits.overageStatus === 'allowed_warning') { |
| 54 | return { |
| 55 | message: "You're close to your extra usage spending limit", |
| 56 | severity: 'warning', |
| 57 | } |
| 58 | } |
| 59 | return null |
| 60 | } |
| 61 | |
| 62 | // ERROR STATES - when limits are rejected |
| 63 | if (limits.status === 'rejected') { |
| 64 | return { message: getLimitReachedText(limits, model), severity: 'error' } |
| 65 | } |
| 66 | |
| 67 | // WARNING STATES - when approaching limits with early warning |
| 68 | if (limits.status === 'allowed_warning') { |
| 69 | // Only show warnings when utilization is above threshold (70%) |
| 70 | // This prevents false warnings after week reset when API may send |
| 71 | // allowed_warning with stale data at low usage levels |
| 72 | const WARNING_THRESHOLD = 0.7 |
| 73 | if ( |
| 74 | limits.utilization !== undefined && |
| 75 | limits.utilization < WARNING_THRESHOLD |
| 76 | ) { |
| 77 | return null |
| 78 | } |
| 79 | |
| 80 | // Don't warn non-billing Team/Enterprise users about approaching plan limits |
| 81 | // if overages are enabled - they'll seamlessly roll into overage |
| 82 | const subscriptionType = getSubscriptionType() |
| 83 | const isTeamOrEnterprise = |
| 84 | subscriptionType === 'team' || subscriptionType === 'enterprise' |
| 85 | const hasExtraUsageEnabled = |
| 86 | getOauthAccountInfo()?.hasExtraUsageEnabled === true |
| 87 | |
| 88 | if ( |
| 89 | isTeamOrEnterprise && |
| 90 | hasExtraUsageEnabled && |
| 91 | !hasClaudeAiBillingAccess() |
| 92 | ) { |
| 93 | return null |
| 94 | } |
| 95 | |
| 96 | const text = getEarlyWarningText(limits) |
| 97 | if (text) { |
| 98 | return { message: text, severity: 'warning' } |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | // No message needed |
no test coverage detected