From 5ead126709a7b22113f3949d4095391169c3f62c Mon Sep 17 00:00:00 2001 From: LeonSGP43 Date: Sun, 3 May 2026 19:36:48 +0800 Subject: [PATCH] fix(doctor): retry DashScope China endpoint --- hermes_cli/doctor.py | 10 ++++++ tests/hermes_cli/test_doctor.py | 54 +++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/hermes_cli/doctor.py b/hermes_cli/doctor.py index fce4b533d9..4b3ce3b7cf 100644 --- a/hermes_cli/doctor.py +++ b/hermes_cli/doctor.py @@ -1225,6 +1225,16 @@ def run_doctor(args): headers=_headers, timeout=10, ) + if ( + _pname == "Alibaba/DashScope" + and not _base + and _resp.status_code == 401 + ): + _resp = httpx.get( + "https://dashscope.aliyuncs.com/compatible-mode/v1/models", + headers=_headers, + timeout=10, + ) if _resp.status_code == 200: print(f"\r {color('✓', Colors.GREEN)} {_label} ") elif _resp.status_code == 401: diff --git a/tests/hermes_cli/test_doctor.py b/tests/hermes_cli/test_doctor.py index 374ef2dea4..abf5f48585 100644 --- a/tests/hermes_cli/test_doctor.py +++ b/tests/hermes_cli/test_doctor.py @@ -652,6 +652,60 @@ def test_run_doctor_kimi_cn_env_is_detected_and_probe_is_null_safe(monkeypatch, assert any(url == "https://api.moonshot.cn/v1/models" for url, _, _ in calls) +def test_run_doctor_dashscope_retries_china_endpoint_after_intl_unauthorized(monkeypatch, tmp_path): + home = tmp_path / ".hermes" + home.mkdir(parents=True, exist_ok=True) + (home / "config.yaml").write_text("memory: {}\n", encoding="utf-8") + (home / ".env").write_text("DASHSCOPE_API_KEY=sk-test\n", encoding="utf-8") + project = tmp_path / "project" + project.mkdir(exist_ok=True) + + monkeypatch.setattr(doctor_mod, "HERMES_HOME", home) + monkeypatch.setattr(doctor_mod, "PROJECT_ROOT", project) + monkeypatch.setattr(doctor_mod, "_DHH", str(home)) + monkeypatch.setenv("DASHSCOPE_API_KEY", "sk-test") + monkeypatch.delenv("DASHSCOPE_BASE_URL", raising=False) + + fake_model_tools = types.SimpleNamespace( + check_tool_availability=lambda *a, **kw: ([], []), + TOOLSET_REQUIREMENTS={}, + ) + monkeypatch.setitem(sys.modules, "model_tools", fake_model_tools) + + try: + from hermes_cli import auth as _auth_mod + monkeypatch.setattr(_auth_mod, "get_nous_auth_status", lambda: {}) + monkeypatch.setattr(_auth_mod, "get_codex_auth_status", lambda: {}) + except ImportError: + pass + + calls = [] + + def fake_get(url, headers=None, timeout=None): + calls.append((url, headers, timeout)) + status = 200 if "dashscope.aliyuncs.com" in url else 401 + return types.SimpleNamespace(status_code=status) + + import httpx + monkeypatch.setattr(httpx, "get", fake_get) + + buf = io.StringIO() + with contextlib.redirect_stdout(buf): + doctor_mod.run_doctor(Namespace(fix=False)) + out = buf.getvalue() + + assert "Alibaba/DashScope" in out + assert "invalid API key" not in out + assert any( + url == "https://dashscope-intl.aliyuncs.com/compatible-mode/v1/models" + for url, _, _ in calls + ) + assert any( + url == "https://dashscope.aliyuncs.com/compatible-mode/v1/models" + for url, _, _ in calls + ) + + @pytest.mark.parametrize("base_url", [None, "https://opencode.ai/zen/go/v1"]) def test_run_doctor_opencode_go_skips_invalid_models_probe(monkeypatch, tmp_path, base_url): home = tmp_path / ".hermes"