Pulls in the useful surface area from @vitobotta's parallel PR #4372
and differentiates on the search_lang default and test coverage.
Credit: the tools_config.py integration, extra_snippets idea, and
BRAVE_API_URL override are all adapted from #4372 (@vitobotta).
Changes:
- hermes_cli/tools_config.py: add Brave Search entry so it shows up in
the `hermes tools` setup wizard alongside the other backends.
- _brave_search: honour BRAVE_API_URL env var (useful for proxies or
self-hosted gateways); read at call time, not import time.
- _normalize_brave_search_results: merge up to two extra_snippets into
the description so callers get the richer context Brave provides
without changing the standard output shape.
- Intentionally do NOT set `search_lang`. Brave auto-detects the query
language, which is what we want for non-English users — #4372
hardcoded `search_lang: "en"` and would downgrade French/other-locale
searches. Added a regression test.
- Docstring explains the search_lang choice and BRAVE_API_URL escape
hatch.
Tests added (5 more, total 20):
- test_does_not_set_search_lang — regression guard
- test_brave_api_url_override — env-based base URL redirection
- test_extra_snippets_merged_into_description
- test_extra_snippets_used_when_description_empty
- test_no_extra_snippets
All 20 Brave tests pass; 60 existing Tavily/config tests still pass.
- web_extract_tool: when backend=brave and FIRECRAWL_API_KEY is
configured, route extract through Firecrawl automatically instead of
returning an error. Falls back to a clear tool_error only when no
Firecrawl credentials are available.
- _brave_search docstring: describe the actual fallback behaviour
(previous wording said extract fell back to Firecrawl but the code
was returning an error unconditionally).
- tests/tools/test_web_tools_brave.py: 15 tests covering request
construction (header auth, param clamping, HTTP error propagation),
response normalization (empty web, null web, missing fields),
backend detection, search dispatch, and both extract fallback paths.