From 3c6ae3713e5daf4bb18f332ebb2bae7f4132b9ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20Fr=C3=B6hlich?= Date: Tue, 2 Jun 2026 13:59:17 +0200 Subject: [PATCH] Models: add Z.AI coding endpoint and GLM vision detection --- routes/model_routes.py | 21 ++++++++++++++++++--- src/chat_helpers.py | 2 ++ static/index.html | 1 + 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/routes/model_routes.py b/routes/model_routes.py index b0fd1f6..28ec1d0 100644 --- a/routes/model_routes.py +++ b/routes/model_routes.py @@ -89,10 +89,13 @@ _PROVIDER_CURATED = { "claude-sonnet-4-5", "claude-haiku-3-5", ], "zai": [ - "glm-5", "glm-4.7", "glm-4.7-flash", + "glm-5", "glm-5.1", "glm-5v-turbo", "glm-4.7", "glm-4.7-flash", "glm-4.6", "glm-4.6v", "glm-4.5", "glm-4.5v", "glm-4.5-air", "glm-4.5-flash", ], + "zai-coding": [ + "glm-5.1", "glm-5v-turbo", "glm-5-turbo", "glm-4.7", "glm-4.5-air", + ], "deepseek": [ "deepseek-chat", "deepseek-reasoner", ], @@ -151,9 +154,14 @@ _HOST_TO_CURATED = ( def _match_provider_curated(base_url: str, provider: str) -> str: """Return the curated-list key for a given endpoint. - Matches the base URL's hostname against known providers; falls back to - the raw provider string from _detect_provider(). + Checks path-based overrides first (for hosts serving multiple plans), + then matches the base URL's hostname against known providers, and + finally falls back to the raw provider string from _detect_provider(). """ + # Path-based overrides for hosts that serve multiple curated lists. + parsed = urlparse(base_url) + if _host_match(base_url, "z.ai") and "/api/coding" in (parsed.path or ""): + return "zai-coding" for domain, key in _HOST_TO_CURATED: if _host_match(base_url, domain): return key @@ -356,6 +364,13 @@ def _probe_endpoint(base_url: str, api_key: str = None, timeout: int = 5) -> Lis if not models: models = [m.get("name") or m.get("model") for m in (data.get("models") or []) if m.get("name") or m.get("model")] if models: + # Z.AI coding plan omits some working models from /models; + # append curated-only entries for that endpoint only. + if _host_match(base, "z.ai") and "/api/coding" in (urlparse(base).path or ""): + _ck = _match_provider_curated(base, None) + for _e in _PROVIDER_CURATED.get(_ck, []): + if _e not in set(models) and not any(m.startswith(_e) for m in models): + models.append(_e) return models except httpx.HTTPStatusError as e: if api_key: diff --git a/src/chat_helpers.py b/src/chat_helpers.py index d690796..e778777 100644 --- a/src/chat_helpers.py +++ b/src/chat_helpers.py @@ -34,6 +34,8 @@ _VISION_MODEL_KEYWORDS = ( # open / local "vision", "llava", "bakllava", "moondream", "pixtral", "minicpm", "internvl", "cogvlm", "qwen-vl", "qwen2-vl", "qwen3-vl", "qwen3vl", + # zhipu / glm (glm-4.5v, glm-4.6v, glm-5v-turbo, etc.) + "glm-4.5v", "glm-4.6v", "glm-5v", ) # Catches the "*-VL-*" / "*VL*" family not covered by a literal keyword above # (e.g. Qwen2.5-VL and various tags): a standalone "vl" token, plus "vlm". diff --git a/static/index.html b/static/index.html index f944240..3e7600f 100644 --- a/static/index.html +++ b/static/index.html @@ -2075,6 +2075,7 @@ +