mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
fix: Address PR review comments for Brave Search
- Fix critical bug: move results initialization inside Firecrawl block to prevent overwriting results from parallel/exa/tavily backends - Fix Brave endpoint path: use 'web/search' instead of '/web/search' - Remove unrelated TAVILY_API_URL env var override - Put Brave last in fallback priority (search-only, falls back to Firecrawl) - Update tests to reflect new fallback order and add Brave-specific tests - Document fallback priority in _get_backend() docstring
This commit is contained in:
parent
d7ec585479
commit
7ab5bfedde
2 changed files with 34 additions and 7 deletions
|
|
@ -397,6 +397,27 @@ class TestBackendSelection:
|
|||
patch.dict(os.environ, {"TAVILY_API_KEY": "tvly-test"}):
|
||||
assert _get_backend() == "tavily"
|
||||
|
||||
def test_fallback_brave_only_key(self):
|
||||
"""Only BRAVE_API_KEY set → 'brave'."""
|
||||
from tools.web_tools import _get_backend
|
||||
with patch("tools.web_tools._load_web_config", return_value={}), \
|
||||
patch.dict(os.environ, {"BRAVE_API_KEY": "brave-test"}):
|
||||
assert _get_backend() == "brave"
|
||||
|
||||
def test_fallback_exa_takes_priority_over_brave(self):
|
||||
"""Exa should win over Brave in the fallback path (Brave is last priority)."""
|
||||
from tools.web_tools import _get_backend
|
||||
with patch("tools.web_tools._load_web_config", return_value={}), \
|
||||
patch.dict(os.environ, {"BRAVE_API_KEY": "brave-test", "EXA_API_KEY": "exa-test"}):
|
||||
assert _get_backend() == "exa"
|
||||
|
||||
def test_fallback_tavily_takes_priority_over_brave(self):
|
||||
"""Tavily should win over Brave in the fallback path."""
|
||||
from tools.web_tools import _get_backend
|
||||
with patch("tools.web_tools._load_web_config", return_value={}), \
|
||||
patch.dict(os.environ, {"TAVILY_API_KEY": "tvly-test", "BRAVE_API_KEY": "brave-test"}):
|
||||
assert _get_backend() == "tavily"
|
||||
|
||||
def test_fallback_tavily_with_firecrawl_prefers_firecrawl(self):
|
||||
"""Tavily + Firecrawl keys, no config → 'firecrawl' (backward compat)."""
|
||||
from tools.web_tools import _get_backend
|
||||
|
|
@ -429,7 +450,8 @@ class TestBackendSelection:
|
|||
def test_fallback_no_keys_defaults_to_firecrawl(self):
|
||||
"""No keys, no config → 'firecrawl' (will fail at client init)."""
|
||||
from tools.web_tools import _get_backend
|
||||
with patch("tools.web_tools._load_web_config", return_value={}):
|
||||
with patch("tools.web_tools._load_web_config", return_value={}), \
|
||||
patch.dict(os.environ, {"BRAVE_API_KEY": ""}, clear=False):
|
||||
assert _get_backend() == "firecrawl"
|
||||
|
||||
def test_invalid_config_falls_through_to_fallback(self):
|
||||
|
|
|
|||
|
|
@ -87,6 +87,11 @@ def _get_backend() -> str:
|
|||
Reads ``web.backend`` from config.yaml (set by ``hermes tools``).
|
||||
Falls back to whichever API key is present for users who configured
|
||||
keys manually without running setup.
|
||||
|
||||
Fallback priority (highest to lowest):
|
||||
firecrawl > parallel > tavily > exa > brave
|
||||
|
||||
Note: Brave is search-only and falls back to Firecrawl for extraction.
|
||||
"""
|
||||
configured = (_load_web_config().get("backend") or "").lower().strip()
|
||||
if configured in ("parallel", "firecrawl", "tavily", "exa", "brave"):
|
||||
|
|
@ -95,12 +100,13 @@ def _get_backend() -> str:
|
|||
# Fallback for manual / legacy config — pick the highest-priority
|
||||
# available backend. Firecrawl also counts as available when the managed
|
||||
# tool gateway is configured for Nous subscribers.
|
||||
# Brave is last because it's search-only (falls back to Firecrawl for extraction).
|
||||
backend_candidates = (
|
||||
("firecrawl", _has_env("FIRECRAWL_API_KEY") or _has_env("FIRECRAWL_API_URL") or _is_tool_gateway_ready()),
|
||||
("parallel", _has_env("PARALLEL_API_KEY")),
|
||||
("tavily", _has_env("TAVILY_API_KEY")),
|
||||
("brave", _has_env("BRAVE_API_KEY")),
|
||||
("exa", _has_env("EXA_API_KEY")),
|
||||
("brave", _has_env("BRAVE_API_KEY")),
|
||||
)
|
||||
for backend, available in backend_candidates:
|
||||
if available:
|
||||
|
|
@ -343,7 +349,7 @@ def _normalize_brave_search_results(response: dict) -> dict:
|
|||
|
||||
# ─── Tavily Client ───────────────────────────────────────────────────────────
|
||||
|
||||
_TAVILY_BASE_URL = os.getenv("TAVILY_API_URL") or "https://api.tavily.com"
|
||||
_TAVILY_BASE_URL = "https://api.tavily.com"
|
||||
|
||||
|
||||
def _tavily_request(endpoint: str, payload: dict) -> dict:
|
||||
|
|
@ -1181,7 +1187,7 @@ def web_search_tool(query: str, limit: int = 5) -> str:
|
|||
|
||||
if backend == "brave":
|
||||
logger.info("Brave Search: '%s' (limit: %d)", query, limit)
|
||||
raw = _brave_request("/web/search", {
|
||||
raw = _brave_request("web/search", {
|
||||
"q": query,
|
||||
"count": min(limit, 20),
|
||||
"search_lang": "en",
|
||||
|
|
@ -1334,11 +1340,10 @@ async def web_extract_tool(
|
|||
# Set backend to firecrawl so the extraction code below runs
|
||||
backend = "firecrawl"
|
||||
|
||||
# Initialize results list before processing
|
||||
results: List[Dict[str, Any]] = []
|
||||
|
||||
# Firecrawl extraction for brave (fallback), firecrawl, or unrecognized backends
|
||||
if backend not in ("parallel", "exa", "tavily"):
|
||||
# Initialize results list before processing
|
||||
results: List[Dict[str, Any]] = []
|
||||
# Determine requested formats for Firecrawl v2
|
||||
formats: List[str] = []
|
||||
if format == "markdown":
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue