mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-09 08:21:50 +00:00
fix(web): make _has_env config-aware so SEARXNG_URL auto-detect honors Hermes config
Follow-up to #34306. The provider fix made SearXNG *usable* with a config-only SEARXNG_URL, but tools/web_tools._has_env still read raw os.getenv, so the backend auto-detect cascade and check_web_api_key remained blind to it — SearXNG worked when explicitly selected but was never auto-selected. Route _has_env (and the SearXNG diagnostic print) through a config-aware _env_value helper mirroring the provider's _searxng_url(). Fixing the shared helper covers every provider key in one place. Adds regression tests for config-only auto-detect and check_web_api_key. See #34290.
This commit is contained in:
parent
2ee8c983c0
commit
7df81d0557
2 changed files with 55 additions and 3 deletions
|
|
@ -267,6 +267,26 @@ class TestGetBackendSearXNG:
|
|||
monkeypatch.setattr(web_tools, "_is_tool_gateway_ready", lambda: False)
|
||||
assert web_tools._get_backend() == "tavily"
|
||||
|
||||
def test_auto_detect_picks_searxng_when_url_only_in_hermes_config(self, monkeypatch):
|
||||
"""#34290 follow-up: a config-only SEARXNG_URL (absent from process env)
|
||||
must still drive auto-detect via the now config-aware ``_has_env``."""
|
||||
from hermes_cli import config as hermes_config
|
||||
from tools import web_tools
|
||||
monkeypatch.setattr(web_tools, "_load_web_config", lambda: {})
|
||||
monkeypatch.delenv("FIRECRAWL_API_KEY", raising=False)
|
||||
monkeypatch.delenv("FIRECRAWL_API_URL", raising=False)
|
||||
monkeypatch.delenv("PARALLEL_API_KEY", raising=False)
|
||||
monkeypatch.delenv("TAVILY_API_KEY", raising=False)
|
||||
monkeypatch.delenv("EXA_API_KEY", raising=False)
|
||||
monkeypatch.delenv("SEARXNG_URL", raising=False)
|
||||
monkeypatch.setattr(
|
||||
hermes_config,
|
||||
"get_env_value",
|
||||
lambda key: "http://config-only:8080" if key == "SEARXNG_URL" else None,
|
||||
)
|
||||
monkeypatch.setattr(web_tools, "_is_tool_gateway_ready", lambda: False)
|
||||
assert web_tools._get_backend() == "searxng"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Integration: check_web_api_key includes searxng
|
||||
|
|
@ -280,6 +300,19 @@ class TestCheckWebApiKey:
|
|||
monkeypatch.setenv("SEARXNG_URL", "http://localhost:8080")
|
||||
assert web_tools.check_web_api_key() is True
|
||||
|
||||
def test_searxng_config_only_satisfies_check_web_api_key(self, monkeypatch):
|
||||
"""#34290 follow-up: config-only SEARXNG_URL satisfies the credential check."""
|
||||
from hermes_cli import config as hermes_config
|
||||
from tools import web_tools
|
||||
monkeypatch.setattr(web_tools, "_load_web_config", lambda: {"backend": "searxng"})
|
||||
monkeypatch.delenv("SEARXNG_URL", raising=False)
|
||||
monkeypatch.setattr(
|
||||
hermes_config,
|
||||
"get_env_value",
|
||||
lambda key: "http://config-only:8080" if key == "SEARXNG_URL" else None,
|
||||
)
|
||||
assert web_tools.check_web_api_key() is True
|
||||
|
||||
def test_no_credentials_fails(self, monkeypatch):
|
||||
from tools import web_tools
|
||||
monkeypatch.setattr(web_tools, "_load_web_config", lambda: {})
|
||||
|
|
|
|||
|
|
@ -110,9 +110,28 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
# ─── Backend Selection ────────────────────────────────────────────────────────
|
||||
|
||||
def _env_value(name: str) -> str:
|
||||
"""Resolve ``name`` via Hermes config-aware env, falling back to process env.
|
||||
|
||||
Mirrors the SearXNG provider's ``_searxng_url()`` so that values set
|
||||
through Hermes' config/.env layer (``hermes config set``, ``hermes tools``)
|
||||
are honored here too — not just raw process-env exports. Without this,
|
||||
a config-only ``SEARXNG_URL`` (or any provider key) leaves the backend
|
||||
auto-detect cascade and ``check_web_api_key()`` blind to it. See #34290.
|
||||
"""
|
||||
try:
|
||||
from hermes_cli.config import get_env_value
|
||||
|
||||
val = get_env_value(name)
|
||||
except Exception:
|
||||
val = None
|
||||
if val is None:
|
||||
val = os.getenv(name, "")
|
||||
return (val or "").strip()
|
||||
|
||||
|
||||
def _has_env(name: str) -> bool:
|
||||
val = os.getenv(name)
|
||||
return bool(val and val.strip())
|
||||
return bool(_env_value(name))
|
||||
|
||||
def _load_web_config() -> dict:
|
||||
"""Load the ``web:`` section from ~/.hermes/config.yaml."""
|
||||
|
|
@ -1204,7 +1223,7 @@ if __name__ == "__main__":
|
|||
elif backend == "tavily":
|
||||
print(" Using Tavily API (https://tavily.com)")
|
||||
elif backend == "searxng":
|
||||
print(f" Using SearXNG (search only): {os.getenv('SEARXNG_URL', '').strip()}")
|
||||
print(f" Using SearXNG (search only): {_env_value('SEARXNG_URL')}")
|
||||
elif backend == "brave-free":
|
||||
print(" Using Brave Search free tier (search only)")
|
||||
elif backend == "ddgs":
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue