Conversation
…ntries Z.AI has two API surfaces (regular /api/paas/v4 and coding /api/coding/paas/v4). An account may only have quota on one. When a zai pool entry is marked exhausted after a 429, the fallback path uses the provider registry's default base_url — which is the regular endpoint — causing permanent failure even when the coding endpoint still works. This change adds two mechanisms: 1. _sync_zai_entry_from_auth_store(): when a zai entry is exhausted, check provider_state.zai.detected_endpoint in auth.json. If runtime resolution detected a different working endpoint, adopt it and clear exhaustion immediately. 2. Re-probe on cooldown expiry: when clear_expired resets an exhausted zai entry after its cooldown, call detect_zai_endpoint() to verify the cached base_url is still valid. If the endpoint changed, update it. If no endpoint works, keep the entry exhausted. Mirrors the existing sync patterns for anthropic, nous, and openai-codex. Fixes: credential pool exhaustion causing wrong zai endpoint fallback
teknium1
left a comment
There was a problem hiding this comment.
Thanks for isolating the Z.AI pool-recovery path. The current main still lacks a Z.AI auth-state sync in agent/credential_pool.py:1381-1476, so the underlying issue remains actionable.
Problems
agent/credential_pool.py:620copies a provider-global detected endpoint without validatingkey_hashagainst the pool entry. Current Z.AI cache reuse is deliberately key-bound inhermes_cli/auth.py:692-697; a pool with multiple keys can therefore inherit another key's endpoint. The added fixture attests/agent/test_credential_pool.py:1669explicitly disables that check.hermes_cli/commands.py:189-190aliases/creditsto/costs, but current main has a separate canonical/creditstop-up flow athermes_cli/commands.py:232,cli.py:8718-8719, andgateway/run.py:9865-9866(shipped in7ba5df0d5).
Suggested changes
- Bind endpoint adoption to the matching credential hash and add a two-key isolation regression test.
- Preserve
/credits; make/costsan alias of/usageif the additional spelling is still wanted.
This is an automated hermes-sweeper review.
| detected = state.get("detected_endpoint") | ||
| if not isinstance(detected, dict): | ||
| return entry | ||
| detected_url = detected.get("base_url", "").rstrip("/") |
There was a problem hiding this comment.
detected_endpoint is keyed to a specific API key on current main (hermes_cli/auth.py:692-697). Verify its key_hash against this entry's access token before adopting the URL; otherwise a cached endpoint for one pooled Z.AI key can overwrite another key's routing. Please add a two-key regression case.
| gateway_only=True), | ||
| CommandDef("usage", "Show token usage and rate limits for the current session", "Info"), | ||
| CommandDef("costs", "Show token usage, costs, and provider rate limits", "Info", | ||
| aliases=("usage", "credits")), |
There was a problem hiding this comment.
Do not make credits an alias here. Current main now has a dedicated /credits balance/top-up flow (hermes_cli/commands.py:232, commit 7ba5df0d5); this mapping would send /credits to the usage handler instead. Preserve /credits and alias only /costs to /usage if needed.
Recover Z.AI credential pool endpoints and register the costs command for endpoint monitoring.