feat(classifier): Anthropic-specific guidance for subscription exhaustion
When an Anthropic Claude Pro/Max OAuth subscription hits the "out of extra usage" 400 (now classified as billing), surface actionable guidance pointing at claude.ai/settings/usage and the cycle-reset option instead of the generic "add credits with that provider" line — which does not apply to a subscription. Folds in the UX from #40073 (@harsh-matchmyflight) without the extra FailoverReason enum; the billing reclass already provides the recovery behavior.
This commit is contained in:
parent
5e64dd9a98
commit
e00800fc89
2 changed files with 66 additions and 0 deletions
|
|
@ -205,6 +205,26 @@ def _billing_or_entitlement_message(
|
|||
|
||||
provider_label = (provider or "").strip() or "the selected provider"
|
||||
model_label = (model or "").strip() or "the selected model"
|
||||
|
||||
# Anthropic Claude Pro/Max OAuth subscriptions surface exhaustion of the
|
||||
# metered "extra usage" bucket as a hard 400 ("You're out of extra
|
||||
# usage"). Point at the exact settings page and note the cycle-reset
|
||||
# option, since the generic "add credits with that provider" line doesn't
|
||||
# apply to a subscription — the user waits for the reset or switches to an
|
||||
# API key.
|
||||
if (provider or "").strip().lower() == "anthropic":
|
||||
lines = [
|
||||
(
|
||||
f"{provider_label} reported that your Claude subscription usage is "
|
||||
f"exhausted for {model_label} (included quota + extra-usage credits)."
|
||||
),
|
||||
"Options: wait for the billing cycle to reset, or add extra usage at "
|
||||
"https://claude.ai/settings/usage",
|
||||
"You can also switch to an Anthropic API key or another provider with "
|
||||
"/model <model> --provider <provider>.",
|
||||
]
|
||||
return "\n".join(lines)
|
||||
|
||||
lines = [
|
||||
(
|
||||
f"{provider_label} reported that billing, credits, or account "
|
||||
|
|
|
|||
46
tests/agent/test_anthropic_billing_guidance.py
Normal file
46
tests/agent/test_anthropic_billing_guidance.py
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
"""Tests for the Anthropic-subscription branch of
|
||||
``agent.conversation_loop._billing_or_entitlement_message``.
|
||||
|
||||
Regression context: Anthropic Claude Pro/Max OAuth subscriptions surface
|
||||
exhaustion of the metered "extra usage" bucket as a hard HTTP 400
|
||||
("You're out of extra usage. Add more at claude.ai/settings/usage..."),
|
||||
which classifies as ``FailoverReason.billing``. The generic billing
|
||||
guidance ("add credits with that provider") is wrong for a subscription —
|
||||
the user waits for the cycle reset or switches to an API key. This branch
|
||||
gives Anthropic-specific, actionable guidance (folds in PR #40073's UX).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from agent.conversation_loop import _billing_or_entitlement_message
|
||||
|
||||
|
||||
def test_anthropic_subscription_exhausted_guidance():
|
||||
"""Anthropic billing guidance points at the exact settings page and
|
||||
the cycle-reset option, not the generic 'add credits' line."""
|
||||
msg = _billing_or_entitlement_message(
|
||||
capability="model access",
|
||||
provider="anthropic",
|
||||
base_url="https://api.anthropic.com",
|
||||
model="claude-opus-4-7",
|
||||
)
|
||||
assert "claude.ai/settings/usage" in msg
|
||||
# Must mention the subscription cycle reset (not generic 'add credits').
|
||||
assert "reset" in msg.lower()
|
||||
# Must still offer the provider-switch escape hatch.
|
||||
assert "/model" in msg
|
||||
# Model name should be interpolated.
|
||||
assert "claude-opus-4-7" in msg
|
||||
|
||||
|
||||
def test_non_anthropic_billing_guidance_unaffected():
|
||||
"""A non-Anthropic provider keeps the generic billing guidance and does
|
||||
NOT get the Anthropic-specific claude.ai settings link."""
|
||||
msg = _billing_or_entitlement_message(
|
||||
capability="model access",
|
||||
provider="openrouter",
|
||||
base_url="https://openrouter.ai/api/v1",
|
||||
model="anthropic/claude-opus-4.7",
|
||||
)
|
||||
assert "claude.ai/settings/usage" not in msg
|
||||
# Generic path still surfaces the OpenRouter credits link.
|
||||
assert "openrouter.ai/settings/credits" in msg
|
||||
Loading…
Add table
Add a link
Reference in a new issue