diff --git a/agent/model_metadata.py b/agent/model_metadata.py index 3571a56469..bad065573a 100644 --- a/agent/model_metadata.py +++ b/agent/model_metadata.py @@ -501,16 +501,19 @@ DEFAULT_CONTEXT_LENGTHS = { # https://platform.minimax.io/docs/api-reference/text-chat-openai "minimax-m3": 1000000, "minimax": 204800, - # GLM — GLM-5.2 ships with a 1M context window (verified empirically: - # needle-in-a-haystack retrieval at 789K prompt tokens succeeded with - # zero errors on api.z.ai/api/coding/paas/v4). Older GLM models - # (5, 5.1, 5-turbo) are ~202K. Longest-key-first substring matching - # ensures "glm-5.2" resolves to 1M while older variants still hit the - # generic 202K fallback. + # GLM — GLM-5.2 and GLM-5.3 ship with a 1M context window. GLM-5.2 was + # verified empirically (needle-in-a-haystack retrieval at 789K prompt + # tokens succeeded with zero errors on api.z.ai/api/coding/paas/v4). + # GLM-5.3 uses the same base model (all gains are post-training) with + # 1M context / 128K max output per docs.z.ai/guides/llm/glm-5.3 + # (verified 2026-08-14). Older GLM models (5, 5.1, 5-turbo) are ~202K. + # Longest-key-first substring matching ensures "glm-5.2"/"glm-5.3" + # resolve to 1M while older variants still hit the generic 202K fallback. "glm-5.2": 1_048_576, # OpenRouter's free GLM-5.2 variant is capped at 256K (live metadata, # 2026-08-21) — longer key wins over the 1M paid entry above. "glm-5.2:free": 256_000, + "glm-5.3": 1_048_576, "glm": 202752, # xAI Grok — xAI /v1/models does not return context_length metadata, # so these hardcoded fallbacks prevent Hermes from probing-down to diff --git a/hermes_cli/auth.py b/hermes_cli/auth.py index ae807b9bfe..c94bf4ab34 100644 --- a/hermes_cli/auth.py +++ b/hermes_cli/auth.py @@ -743,8 +743,8 @@ ZAI_ENDPOINTS = [ # (id, base_url, probe_models, label) ("global", "https://api.z.ai/api/paas/v4", ["glm-5"], "Global"), ("cn", "https://open.bigmodel.cn/api/paas/v4", ["glm-5"], "China"), - ("coding-global", "https://api.z.ai/api/coding/paas/v4", ["glm-5.2", "glm-5.1", "glm-5v-turbo", "glm-4.7"], "Global (Coding Plan)"), - ("coding-cn", "https://open.bigmodel.cn/api/coding/paas/v4", ["glm-5.2", "glm-5.1", "glm-5v-turbo", "glm-4.7"], "China (Coding Plan)"), + ("coding-global", "https://api.z.ai/api/coding/paas/v4", ["glm-5.3", "glm-5.2", "glm-5.1", "glm-5v-turbo", "glm-4.7"], "Global (Coding Plan)"), + ("coding-cn", "https://open.bigmodel.cn/api/coding/paas/v4", ["glm-5.3", "glm-5.2", "glm-5.1", "glm-5v-turbo", "glm-4.7"], "China (Coding Plan)"), ] diff --git a/hermes_cli/models.py b/hermes_cli/models.py index d607a63a7b..63efab9681 100644 --- a/hermes_cli/models.py +++ b/hermes_cli/models.py @@ -116,7 +116,8 @@ OPENROUTER_MODELS: list[tuple[str, str]] = [ # MiniMax ("minimax/minimax-m3", ""), # Z-AI - ("z-ai/glm-5.2", "default"), + ("z-ai/glm-5.3", "default"), + ("z-ai/glm-5.2", ""), ("z-ai/glm-5.1", ""), # Xiaomi ("xiaomi/mimo-v2.5-pro", ""), @@ -294,6 +295,7 @@ _PROVIDER_MODELS: dict[str, list[str]] = { # MiniMax "minimax/minimax-m3", # Z-AI + "z-ai/glm-5.3", "z-ai/glm-5.2", "z-ai/glm-5.1", # Xiaomi @@ -373,6 +375,7 @@ _PROVIDER_MODELS: dict[str, list[str]] = { "gemini-3.1-flash-lite-preview", ], "zai": [ + "glm-5.3", "glm-5.2", "glm-5.1", "glm-5", @@ -391,6 +394,7 @@ _PROVIDER_MODELS: dict[str, list[str]] = { "nvidia/nemotron-3-nano-omni-30b-a3b-reasoning", # Third-party agentic models hosted on build.nvidia.com # (map to OpenRouter defaults — users get familiar picks on NIM) + "z-ai/glm-5.3", "z-ai/glm-5.2", "moonshotai/kimi-k2.6", "minimaxai/minimax-m3", @@ -542,6 +546,7 @@ _PROVIDER_MODELS: dict[str, list[str]] = { "minimax-m3", "minimax-m2.7", "minimax-m2.5", + "glm-5.3", "glm-5.2", "glm-5.1", "glm-5", diff --git a/plugins/model-providers/zai/__init__.py b/plugins/model-providers/zai/__init__.py index 322068617e..2828caff92 100644 --- a/plugins/model-providers/zai/__init__.py +++ b/plugins/model-providers/zai/__init__.py @@ -47,22 +47,28 @@ def _model_supports_thinking(model: str | None) -> bool: def _is_glm_5_2(model: str | None) -> bool: - """Detect GLM-5.2 across the alias spellings providers use. + """Detect GLM-5.2/5.3 (reasoning_effort-capable) across alias spellings. - Covers the canonical ``glm-5.2`` plus the ``glm-5-2`` / ``glm-5p2`` - variants seen on relays (Fireworks ``glm-5p2``, etc.) and any - vendor-prefixed form (``z-ai/glm-5.2``, ``zai-org-glm-5-2``). + Covers the canonical ``glm-5.2``/``glm-5.3`` plus the ``glm-5-2`` / + ``glm-5p2`` variants seen on relays (Fireworks ``glm-5p2``, etc.) and any + vendor-prefixed form (``z-ai/glm-5.2``, ``zai-org-glm-5-2``). GLM-5.3 + uses the same base model as 5.2 (post-training gains only) and exposes + the same ``reasoning_effort`` knob (verified live 2026-08-14: the + coding-plan endpoint accepts ``reasoning_effort: high`` for glm-5.3). """ m = (model or "").strip().lower() if not m: return False - return any(token in m for token in ("glm-5.2", "glm-5-2", "glm-5p2")) + return any( + token in m + for token in ("glm-5.2", "glm-5-2", "glm-5p2", "glm-5.3", "glm-5-3", "glm-5p3") + ) def _glm_5_2_reasoning_effort(reasoning_config: dict | None) -> str | None: - """Map Hermes reasoning effort onto GLM-5.2's native ``high``/``max``. + """Map Hermes reasoning effort onto GLM-5.2/5.3's native ``high``/``max``. - GLM-5.2 only supports two enabled effort levels. ``xhigh``/``max``/``ultra`` + These models only support two enabled effort levels. ``xhigh``/``max``/``ultra`` request the top tier; everything else that is enabled requests ``high`` (its minimum thinking level). When reasoning is explicitly disabled, or no effort preference is supplied, the server default is left untouched.