feat(providers): split zai into 4 plans (Global/China × direct API/Coding Plan) - #13500
Closed
yuanmingyi wants to merge 1 commit into
Closed
yuanmingyi wants to merge 1 commit into
yuanmingyi wants to merge 1 commit into
Conversation
…obal + China)
Previously a single `zai` provider served Z.AI / GLM across all plans, endpoints,
and billing modes via runtime endpoint-probing. Split into four explicit providers
so users pick their plan once and Hermes routes cleanly:
- zai — Z.AI (Global) — api.z.ai/api/paas/v4
- zai-cn — Zhipu AI (China) — open.bigmodel.cn/api/paas/v4
- zai-coding-global — Z.AI Coding Plan — api.z.ai/api/coding/paas/v4
- zai-coding-cn — Zhipu AI Coding Plan — open.bigmodel.cn/api/coding/paas/v4
Key changes:
- PROVIDER_REGISTRY + HERMES_OVERLAYS declare each plan with its own env vars
(ZAI_API_KEY, GLM_API_KEY, ZAI_CODING_API_KEY, GLM_CODING_API_KEY) and base-URL
override vars. Models.dev mapping uses per-plan IDs (zai / zhipuai /
zai-coding-plan / zhipuai-coding-plan) so /model and /provider show distinct
catalogs and display names.
- Curated `_PROVIDER_MODELS` lists per plan: direct-API plans get the full
9-model catalog (glm-5.1, glm-5, glm-5v-turbo, glm-5-turbo, glm-4.7,
glm-4.7-flashx, glm-4.6, glm-4.5, glm-4.5-air); coding plans get the
4-model subset (glm-5.1, glm-5-turbo, glm-4.7, glm-4.5-air).
- Removed legacy ZAI endpoint-probing (`detect_zai_endpoint`,
`_resolve_zai_base_url`) — each plan's URL is now static.
- Aux-client defaults: zai/zai-cn -> glm-4.7-flashx; zai-coding-* -> glm-4.7.
Vision override: zai/zai-cn -> glm-5v-turbo.
- Dot-preservation in run_agent._anthropic_preserve_dots() extended to all
four plans (prevents glm-4.7 from being mangled to glm-47).
- Doctor / status / dump / setup / config OPTIONAL_ENV_VARS updated with
per-plan entries and correct env-var mappings.
- trajectory_compressor._detect_provider now checks host + path to route
coding-plan URLs correctly (previously relied on base_url_host_matches
which ignored path components).
Legacy compatibility:
- `GLM_API_KEY` is retained as a last-resort fallback in zai's env tuple
so existing `provider: zai` configs with only GLM_API_KEY set keep working.
- PROVIDER_REGISTRY declares `zai-cn` before `zai` so auto-detect with only
GLM_API_KEY still prefers `zai-cn` (correct plan), while explicit
`provider: zai` can still read the GLM key as a fallback.
- Aliases: `glm`/`zhipu` now map to `zai-cn` (was `zai`); `z-ai`/`z.ai`/`grok`
unchanged.
This was referenced May 25, 2026
11 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Z.AI ships four distinct billing/endpoint combinations (Global direct, China direct, Coding Plan Global, Coding Plan China) behind one user-facing name. The single pre-existing
zaiprovider tried to paper over this at runtime by probing endpoints with the user's key to find the working one — slow, fragile, and gave users no way to pin a plan. This PR splitszaiinto four explicit Hermes providers so users pick their plan once and credentials resolve deterministically.zaizaiapi.z.ai/api/paas/v4ZAI_API_KEYzai-cnzhipuaiopen.bigmodel.cn/api/paas/v4GLM_API_KEYzai-coding-globalzai-coding-planapi.z.ai/api/coding/paas/v4ZAI_CODING_API_KEYzai-coding-cnzhipuai-coding-planopen.bigmodel.cn/api/coding/paas/v4GLM_CODING_API_KEYDisplay names, model catalogs, and capability metadata are sourced from models.dev's per-plan entries. Legacy
provider: zaiconfigs with onlyGLM_API_KEYset continue to work — see Compatibility below.Changes
hermes_cli/auth.py— four distinctPROVIDER_REGISTRYentries with per-plan env vars and static base URLs. Droppeddetect_zai_endpoint/_resolve_zai_base_url— endpoints no longer probed.zai-cndeclared beforezaiso auto-detect with onlyGLM_API_KEYstill prefers the China plan.hermes_cli/providers.py—HERMES_OVERLAYSgains three new entries (zai-cn,zai-coding-cn,zai-coding-global).ALIASESnow routesglm/zhipu→zai-cn;z-ai/z.ai→zaiunchanged.agent/models_dev.py—PROVIDER_TO_MODELS_DEVmaps each Hermes id to its distinct models.dev catalog so/modeland/providerpickers show the right per-plan display name and model list.hermes_cli/models.py— curated_PROVIDER_MODELS:zai,zai-cn):glm-5.1, glm-5, glm-5v-turbo, glm-5-turbo, glm-4.7, glm-4.7-flashx, glm-4.6, glm-4.5, glm-4.5-airzai-coding-*):glm-5.1, glm-5-turbo, glm-4.7, glm-4.5-airagent/auxiliary_client.py— aux-model defaults:zai/zai-cn→glm-4.7-flashx;zai-coding-*→glm-4.7. Vision override:zai/zai-cn→glm-5v-turbo.run_agent.py—_anthropic_preserve_dots()extended to all four plans soglm-4.7/glm-5.1aren't mangled at API-call time.agent/model_metadata.py—_PROVIDER_PREFIXESgains the two coding-plan slugs forzai-coding-*/glm-5.1prefix stripping.hermes_cli/model_normalize.py— same four slugs added to_MATCHING_PREFIX_STRIP_PROVIDERS.hermes_cli/doctor.py— two new_apikey_providersprobes (api.z.ai/api/coding/paas/v4/models,open.bigmodel.cn/api/coding/paas/v4/models);_PROVIDER_ENV_HINTSgains the six new env vars so.envwith only coding-plan keys is recognised as provider-configured.hermes_cli/status.py—keys+apikey_providersdicts list all four plans; column widened from 12 → 20 to fitZhipu AI Coding Plan.hermes_cli/dump.py/hermes_cli/setup.py/hermes_cli/config.py/hermes_cli/main.py/cli.py— per-plan env-var mappings, vision-setup labels, fallback config comments,--providerchoices, docstrings updated.gateway/platforms/qqbot/adapter.py— STT_PROVIDER_BASE_URLSrecognises all four zai slugs (plus legacyglmalias) and picksglm-asras default model; all China/Global variants map toopen.bigmodel.cn/api/paas/v4since GLM-ASR is hosted only there.trajectory_compressor.py—_detect_providernow inspects URL path to distinguish Coding Plan from direct API (previousbase_url_host_matchescall with a path string was dead code because the helper only compares hostnames).Compatibility
A user upgrading with
model.provider: zaiand onlyGLM_API_KEYset would otherwise break becausezai's env tuple is now(ZAI_API_KEY, Z_AI_API_KEY). Rather than add a migration shim,GLM_API_KEYis kept as a last-resort fallback inzai's env tuple. On upgrade:provider: zai+ onlyGLM_API_KEY→ key resolves via fallback; request hitsapi.z.ai(may 401 if the key was issued for Zhipu/bigmodel). Real API error beats the pre-fix empty-key bailout; runninghermes modelre-picks the correct plan.provider: zai-cn+GLM_API_KEY→ clean.GLM_API_KEY→zai-cn(registry order reversal ensures this).ZAI_API_KEYalways wins overGLM_API_KEYwhen both present.Validation
All 457 relevant tests pass. Added coverage for per-plan registry entries, legacy
GLM_API_KEYfallback, auto-detect priority, and static-endpoint resolution.🤖 Generated with Claude Code