stage-313 absorb: gate _resolve_configured_provider_id alias resolution + harden bootstrap test isolation

Two in-stage fixes for v0.51.19 batch:

1) api/config.py — add resolve_alias=False param to
   _resolve_configured_provider_id() and pass it from
   resolve_model_provider(). The PR #1818 swap from
   _resolve_provider_alias() to _resolve_configured_provider_id()
   was correct for active-provider/badge surfaces but broke #1625's
   local-server-provider literal-preservation contract: 'ollama' →
   'custom' and 'lm-studio' → 'lmstudio' alias-collapse caused
   _LOCAL_SERVER_PROVIDERS membership check to miss, breaking the
   model-id full-path preservation for LM Studio/Ollama. The new
   flag preserves the raw provider value when called from
   resolve_model_provider, and named-custom-slug + base-url
   fallback both still run unchanged.

2) tests/test_bootstrap_discover_agent.py — pin Path.home() in
   _isolate_discover_agent_dir so the hard-coded
   'Path.home() / .hermes / hermes-agent' / 'Path.home() /
   hermes-agent' candidates in discover_agent_dir() can't pick up
   the dev machine's real install. The original PR #1817 isolation
   helper covered HERMES_HOME, HERMES_WEBUI_AGENT_DIR, and
   REPO_ROOT but missed the Path.home() leak.

Both surfaced on full pytest pre-release gate, fixed in stage,
ship in v0.51.19. Tests: full suite green.
This commit is contained in:
hermes-agent
2026-05-07 17:07:48 +00:00
parent fc8cab4d1c
commit 1f702c7569
2 changed files with 31 additions and 0 deletions

View File

@@ -789,11 +789,34 @@ def _resolve_configured_provider_id(
config_obj: dict | None = None,
*,
base_url: object = None,
resolve_alias: bool = True,
) -> str:
"""Normalize a configured provider id.
When ``resolve_alias`` is True (default, used for active-provider /
badge surfaces), falls through to ``_resolve_provider_alias`` after the
named-custom check. When False (used by ``resolve_model_provider``),
preserves the raw provider value so downstream local-server detection
(`_LOCAL_SERVER_PROVIDERS` membership in #1625) sees the original name
like ``ollama`` / ``lm-studio`` rather than alias-collapsed ``custom`` /
``lmstudio``. The base-url-to-named-slug fallback still runs in both
modes when applicable.
See in-stage absorption note on stage-313 for the #1625 regression that
motivated the ``resolve_alias`` flag.
"""
named_slug = _named_custom_provider_slug_for_provider(provider, config_obj)
if named_slug:
return named_slug
if not resolve_alias:
raw = str(provider or "").strip().lower()
if base_url and raw == "custom":
by_base_url = _named_custom_provider_slug_for_base_url(base_url, config_obj)
if by_base_url:
return by_base_url
return str(provider or "")
resolved = _resolve_provider_alias(provider)
if (
base_url
@@ -1423,6 +1446,7 @@ def resolve_model_provider(model_id: str) -> tuple:
model_cfg.get("provider"),
cfg,
base_url=config_base_url,
resolve_alias=False,
)
# Heal legacy ``provider: local`` entries (written by WebUI < v0.50.252)

View File

@@ -54,6 +54,13 @@ def _isolate_discover_agent_dir(monkeypatch, tmp_path, hermes_path):
# Force REPO_ROOT.parent to a dir that won't accidentally contain a
# `hermes-agent` sibling on the dev machine running these tests.
monkeypatch.setattr(bootstrap, "REPO_ROOT", tmp_path / "isolated-repo-root")
# Pin Path.home() to a directory with no `.hermes/hermes-agent` or
# `hermes-agent` so the hard-coded `Path.home() / ".hermes" / "hermes-agent"`
# / `Path.home() / "hermes-agent"` candidates in `discover_agent_dir()`
# cannot pick up the dev machine's real install. Stage-313 absorbed
# this in-stage after the original test file isolated only env vars
# and REPO_ROOT, missing the Path.home() leakage.
monkeypatch.setattr(bootstrap.Path, "home", classmethod(lambda cls: tmp_path / "isolated-home"))
def test_discovers_agent_dir_from_hermes_shebang(monkeypatch, tmp_path):