Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions hermes_cli/doctor.py
Original file line number Diff line number Diff line change
Expand Up @@ -824,11 +824,21 @@ def run_doctor(args):
or provider_policy_id == "custom"
or provider_policy_id.startswith("custom:")
)
# Fireworks native model IDs use a multi-segment path shape such as
# ``accounts/fireworks/models/qwen3p7-plus``. That contains slashes,
# but it is not an aggregator-style ``vendor/model`` slug and is
# valid for the native Fireworks provider.
is_native_fireworks_model_id = (
provider_policy_id == "fireworks"
and default_model.startswith("accounts/")
and "/models/" in default_model
)
if (
default_model
and "/" in default_model
and provider_policy_id
and not provider_accepts_vendor_slug
and not is_native_fireworks_model_id
):
check_warn(
f"model.default '{default_model}' uses a vendor/model slug but provider is '{provider_raw}'",
Expand Down
56 changes: 56 additions & 0 deletions tests/hermes_cli/test_doctor.py
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,62 @@ def test_run_doctor_accepts_hermes_provider_ids_that_catalog_aliases(
)


def test_run_doctor_accepts_native_fireworks_account_model_ids(monkeypatch, tmp_path):
home = tmp_path / ".hermes"
home.mkdir(parents=True, exist_ok=True)
(home / ".env").write_text("FIREWORKS_API_KEY=***\n", encoding="utf-8")
(home / "config.yaml").write_text(
"model:\n"
" provider: fireworks\n"
" default: accounts/fireworks/models/qwen3p7-plus\n",
encoding="utf-8",
)

monkeypatch.setattr(doctor_mod, "HERMES_HOME", home)
monkeypatch.setattr(doctor_mod, "PROJECT_ROOT", tmp_path / "project")
monkeypatch.setattr(doctor_mod, "_DHH", str(home))
(tmp_path / "project").mkdir(exist_ok=True)

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.setitem(
_auth_mod.PROVIDER_REGISTRY,
"fireworks",
_auth_mod.ProviderConfig(
id="fireworks",
name="Fireworks AI",
auth_type="api_key",
api_key_env_vars=("FIREWORKS_API_KEY",),
),
)
monkeypatch.setattr(_auth_mod, "get_nous_auth_status", lambda: {})
monkeypatch.setattr(_auth_mod, "get_codex_auth_status", lambda: {})
monkeypatch.setattr(_auth_mod, "get_xai_oauth_auth_status", lambda: {})
monkeypatch.setattr(_auth_mod, "get_auth_status", lambda provider: {"configured": True})
except Exception:
pass

buf = io.StringIO()
with contextlib.redirect_stdout(buf):
doctor_mod.run_doctor(Namespace(fix=False))

out = buf.getvalue()
assert "model.provider 'fireworks' is not a recognised provider" not in out
assert "model.provider 'fireworks' is unknown" not in out
assert (
"model.default 'accounts/fireworks/models/qwen3p7-plus' uses a vendor/model slug "
"but provider is 'fireworks'"
not in out
)
assert "Either set model.provider to 'openrouter', or drop the vendor prefix." not in out


def test_run_doctor_accepts_vendor_slugs_for_named_custom_provider(monkeypatch, tmp_path):
home = tmp_path / ".hermes"
home.mkdir(parents=True, exist_ok=True)
Expand Down
Loading