mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
feat(gemini): block free-tier keys at setup + surface guidance on 429 (#15100)
Google AI Studio's free tier (<= 250 req/day for gemini-2.5-flash) is exhausted in a handful of agent turns, so the setup wizard now refuses to wire up Gemini when the supplied key is on the free tier, and the runtime 429 handler appends actionable billing guidance. Setup-time probe (hermes_cli/main.py): - `_model_flow_api_key_provider` fires one minimal generateContent call when provider_id == 'gemini' and classifies the response as free/paid/unknown via x-ratelimit-limit-requests-per-day header or 429 body containing 'free_tier'. - Free -> print block message, refuse to save the provider, return. - Paid -> 'Tier check: paid' and proceed. - Unknown (network/auth error) -> 'could not verify', proceed anyway. Runtime 429 handler (agent/gemini_native_adapter.py): - `gemini_http_error` appends billing guidance when the 429 error body mentions 'free_tier', catching users who bypass setup by putting GOOGLE_API_KEY directly in .env. Tests: 21 unit tests for the probe + error path, 4 tests for the setup-flow block. All 67 existing gemini tests still pass.
This commit is contained in:
parent
346601ca8d
commit
3aa1a41e88
4 changed files with 463 additions and 0 deletions
|
|
@ -3930,12 +3930,71 @@ def _model_flow_api_key_provider(config, provider_id, current_model=""):
|
|||
print("Cancelled.")
|
||||
return
|
||||
save_env_value(key_env, new_key)
|
||||
existing_key = new_key
|
||||
print("API key saved.")
|
||||
print()
|
||||
else:
|
||||
print(f" {pconfig.name} API key: {existing_key[:8]}... ✓")
|
||||
print()
|
||||
|
||||
# Gemini free-tier gate: free-tier daily quotas (<= 250 RPD for Flash)
|
||||
# are exhausted in a handful of agent turns, so refuse to wire up the
|
||||
# provider with a free-tier key. Probe is best-effort; network or auth
|
||||
# errors fall through without blocking.
|
||||
if provider_id == "gemini" and existing_key:
|
||||
try:
|
||||
from agent.gemini_native_adapter import probe_gemini_tier
|
||||
except Exception:
|
||||
probe_gemini_tier = None
|
||||
if probe_gemini_tier is not None:
|
||||
print(" Checking Gemini API tier...")
|
||||
probe_base = (
|
||||
(get_env_value(base_url_env) if base_url_env else "")
|
||||
or os.getenv(base_url_env or "", "")
|
||||
or pconfig.inference_base_url
|
||||
)
|
||||
tier = probe_gemini_tier(existing_key, probe_base)
|
||||
if tier == "free":
|
||||
print()
|
||||
print(
|
||||
"❌ This Google API key is on the free tier "
|
||||
"(<= 250 requests/day for gemini-2.5-flash)."
|
||||
)
|
||||
print(
|
||||
" Hermes typically makes 3-10 API calls per user turn "
|
||||
"(tool iterations + auxiliary tasks),"
|
||||
)
|
||||
print(
|
||||
" so the free tier is exhausted after a handful of "
|
||||
"messages and cannot sustain"
|
||||
)
|
||||
print(" an agent session.")
|
||||
print()
|
||||
print(
|
||||
" To use Gemini with Hermes, enable billing on your "
|
||||
"Google Cloud project and regenerate"
|
||||
)
|
||||
print(
|
||||
" the key in a billing-enabled project: "
|
||||
"https://aistudio.google.com/apikey"
|
||||
)
|
||||
print()
|
||||
print(
|
||||
" Alternatives with workable free usage: DeepSeek, "
|
||||
"OpenRouter (free models), Groq, Nous."
|
||||
)
|
||||
print()
|
||||
print("Not saving Gemini as the default provider.")
|
||||
return
|
||||
if tier == "paid":
|
||||
print(" Tier check: paid ✓")
|
||||
else:
|
||||
# "unknown" -- network issue, auth problem, unexpected response.
|
||||
# Don't block; the runtime 429 handler will surface free-tier
|
||||
# guidance if the key turns out to be free tier.
|
||||
print(" Tier check: could not verify (proceeding anyway).")
|
||||
print()
|
||||
|
||||
# Optional base URL override
|
||||
current_base = ""
|
||||
if base_url_env:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue