From ddbef9cd79a4348612f0b9bf0bc5f03c5bc9bd17 Mon Sep 17 00:00:00 2001 From: Xie <38648863+EvenXieWF@users.noreply.github.com> Date: Mon, 3 Aug 2026 09:40:43 +0800 Subject: [PATCH] fix(auxiliary): keep ZAI Coding Plan routing --- agent/auxiliary_client.py | 15 +++++++++++---- tests/agent/test_minimax_auxiliary_url.py | 18 ++++++++++++++++-- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/agent/auxiliary_client.py b/agent/auxiliary_client.py index 307d0be442..f5e827b7c5 100644 --- a/agent/auxiliary_client.py +++ b/agent/auxiliary_client.py @@ -1271,13 +1271,20 @@ def _to_openai_base_url(base_url: str) -> str: Anthropic-**only** custom gateways (path ends in ``/anthropic`` but has no sibling ``/v1``) must keep their path; rewriting them to ``/v1`` yields 404 on compression/vision/title_generation (#83642). + + ZAI exposes its general API and Coding Plan on separate endpoints. Its + Anthropic-compatible Coding Plan endpoint maps to ``/api/coding/paas/v4`` + on the OpenAI wire, not the general ``/api/paas/v4`` endpoint. Rewriting + to the general endpoint changes the billing pool and can return a false + insufficient-balance error for a valid Coding Plan key. """ url = str(base_url or "").strip().rstrip("/") if url.endswith("/anthropic"): - # ZAI (open.bigmodel.cn) uses /api/anthropic for Anthropic wire - # but /api/paas/v4 for OpenAI wire — the generic /v1 rewrite is wrong. - if "open.bigmodel.cn" in url or "bigmodel" in url: - rewritten = url[: -len("/anthropic")] + "/paas/v4" + # ZAI uses /api/anthropic for the Coding Plan's Anthropic wire. The + # matching OpenAI-wire endpoint is /api/coding/paas/v4; /api/paas/v4 + # is the independently billed general API. + if "open.bigmodel.cn" in url or "bigmodel" in url or "api.z.ai" in url: + rewritten = url[: -len("/anthropic")] + "/coding/paas/v4" logger.debug("Auxiliary client: rewrote ZAI base URL %s → %s", url, rewritten) return rewritten if _is_dual_surface_anthropic_host(url): diff --git a/tests/agent/test_minimax_auxiliary_url.py b/tests/agent/test_minimax_auxiliary_url.py index 581310802c..0f07670c7c 100644 --- a/tests/agent/test_minimax_auxiliary_url.py +++ b/tests/agent/test_minimax_auxiliary_url.py @@ -1,7 +1,9 @@ -"""Tests for MiniMax auxiliary client URL normalization. +"""Tests for Anthropic-to-OpenAI auxiliary URL normalization. MiniMax and MiniMax-CN set inference_base_url to the /anthropic path. -The auxiliary client uses the OpenAI SDK, which needs /v1 instead. +The auxiliary client uses the OpenAI SDK, which needs /v1 instead. ZAI's +Anthropic endpoint belongs to Coding Plan, whose OpenAI-compatible peer is the +separately billed /api/coding/paas/v4 endpoint. """ import sys @@ -37,5 +39,17 @@ class TestToOpenaiBaseUrl: url = "https://minimax.io.evil.example.com/anthropic" assert _to_openai_base_url(url) == url + def test_zai_anthropic_routes_to_coding_plan_openai_endpoint(self): + assert ( + _to_openai_base_url("https://api.z.ai/api/anthropic") + == "https://api.z.ai/api/coding/paas/v4" + ) + + def test_bigmodel_anthropic_routes_to_coding_plan_openai_endpoint(self): + assert ( + _to_openai_base_url("https://open.bigmodel.cn/api/anthropic") + == "https://open.bigmodel.cn/api/coding/paas/v4" + ) + def test_none(self): assert _to_openai_base_url(None) == ""