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:
@@ -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.
|
||||
|
||||
@@ -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) == ""
|
||||
|
||||
Reference in New Issue
Block a user