fix(agent): anchor ZAI/Kimi base_url host matching to avoid substring false positives

_to_openai_base_url() matched ZAI (open.bigmodel.cn, api.z.ai, bare
"bigmodel") and Kimi (api.kimi.com) via `substring in url`, so any custom
gateway whose base_url happened to contain one of those strings as a path
segment (e.g. a reverse-proxy prefix like /proxy/bigmodel-fallback/) was
silently misrouted to the wrong OpenAI-wire endpoint shape.

This is the same false-positive class 6f33f510e8 just fixed for the
MiniMax branch in the same function by switching to base_url_host_matches()
(hostname-anchored). Apply the same fix to the ZAI and Kimi branches, which
that commit didn't touch. Drops the bare "bigmodel" substring check since
open.bigmodel.cn is the only canonical bigmodel-family host referenced
anywhere else in the codebase (agent/model_metadata.py, hermes_cli/auth.py).

Added regression tests mirroring the MiniMax marker-in-path tests added in
the same commit.
This commit is contained in:
pierrenode
2026-08-14 03:20:42 +03:00
committed by Teknium
parent 42a1db4c64
commit 2d9f116351
2 changed files with 21 additions and 2 deletions
+2 -2
View File
@@ -1283,7 +1283,7 @@ def _to_openai_base_url(base_url: str) -> str:
# 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:
if base_url_host_matches(url, "open.bigmodel.cn") or base_url_host_matches(url, "api.z.ai"):
rewritten = url[: -len("/anthropic")] + "/coding/paas/v4"
logger.debug("Auxiliary client: rewrote ZAI base URL %s → %s", url, rewritten)
return rewritten
@@ -1297,7 +1297,7 @@ def _to_openai_base_url(base_url: str) -> str:
url,
)
return url
if "api.kimi.com" in url and url.endswith("/coding"):
if base_url_host_matches(url, "api.kimi.com") and url.endswith("/coding"):
# Kimi Code uses /coding/v1/messages for Anthropic SDK (appends /v1/messages)
# but /coding/v1/chat/completions for OpenAI SDK (appends /chat/completions)
# Without /v1 here, OpenAI SDK hits /coding/chat/completions — a 404.
+19
View File
@@ -51,5 +51,24 @@ class TestToOpenaiBaseUrl:
== "https://open.bigmodel.cn/api/coding/paas/v4"
)
def test_bigmodel_marker_in_path_does_not_false_positive(self):
"""Host-anchored matching: 'bigmodel' in the path must not trigger rewrite."""
url = "https://gateway.example.com/proxy/bigmodel-fallback/anthropic"
assert _to_openai_base_url(url) == url
def test_zai_marker_in_path_does_not_false_positive(self):
url = "https://gateway.example.com/api.z.ai-mirror/anthropic"
assert _to_openai_base_url(url) == url
def test_kimi_coding_host_rewritten(self):
assert (
_to_openai_base_url("https://api.kimi.com/coding")
== "https://api.kimi.com/coding/v1"
)
def test_kimi_marker_in_path_does_not_false_positive(self):
url = "https://gateway.example.com/some/api.kimi.com-proxy/coding"
assert _to_openai_base_url(url) == url
def test_none(self):
assert _to_openai_base_url(None) == ""