Skip to content

feat(tools): hermes tools web reorder — interactive search provider priority - #53152

Closed
Icather wants to merge 3 commits into
NousResearch:mainfrom
Icather:feat/hermes-tools-web-reorder
Closed

feat(tools): hermes tools web reorder — interactive search provider priority#53152
Icather wants to merge 3 commits into
NousResearch:mainfrom
Icather:feat/hermes-tools-web-reorder

Conversation

@Icather

@Icather Icather commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

New users adding search providers via #53149 get all backends in a hardcoded order with no way to re-prioritize without editing config.yaml by hand. This adds hermes tools web reorder — an interactive command that lists the current fallback order, accepts a space-separated reorder from the user, validates it, and writes back to web.fallback_backends in config.

Depends on: #53149 (providers) and #53151 (fallback chain)

Type of Change

  • New feature (non-breaking addition)

Changes Made

  • hermes_cli/tools_config.py_tools_web_reorder() function (~90 lines): interactive prompt, validation, config write; _provider_display_name() helper for human-readable labels
  • hermes_cli/subcommands/tools.pyhermes tools web reorder sub-subparser registration

How to Test

  1. Merge feat(web): add 9 search providers — serper, baidu, bocha, qiniu-baidu, serpapi, jina, google-cse, sogou, 360-search #53149 and feat(web): multi-source fallback chain and search_engine parameter #53151 first
  2. Run hermes tools web reorder
  3. Should show current provider order with numbered indices
  4. Enter e.g. 3 1 2 to reorder — should validate and save

Checklist

  • My commit messages follow Conventional Commits
  • I searched for existing PRs
  • My PR contains only changes related to this feature
  • I have tested on my platform: Windows 10
  • I have added tests for my changes

Icather added 3 commits June 27, 2026 00:03
…u-baidu, serpapi, jina, google-cse, sogou, 360-search)

v0.17 removed the Parallel free MCP fallback (NousResearch#46350), sharply reducing free search options. This adds 9 new providers as plugins following the existing brave-free/ddgs pattern, registered in backend_candidates in composite quality-score order after the existing backends.

New functional providers (search-only):
- serper      — Google SERP, 2,500 free queries, no credit card
- baidu       — Baidu AI Search, 100/day free, native Chinese content
- bocha       — Chinese market leader, 1,000 free starter queries
- qiniu-baidu — Qiniu Cloud Baidu, 3M tokens for new users
- serpapi     — Multi-engine, 100/month free
- jina        — Full-page extraction, 10M tokens free (blocked in China)
- google-cse  — Google Custom Search, 100/day (blocked in China)

Registry-only entries (no public API, listed for completeness):
- sogou, 360-search

Two prior attempts (NousResearch#41015 Serper by ViezeVingertjes, NousResearch#35690 fallback by jonathanwxh-cell) were self-closed without review. This salages their approach with a complete provider surface covering both Western and Chinese search engines.

Changes:
- plugins/web/*/ — 27 new files (provider.py, plugin.yaml, __init__.py per backend)
- tools/web_tools.py — +9 entries in _KNOWN_WEB_BACKENDS set, +9 in backend_candidates tuple, +_check_provider_available() helper, generic plugin probe in _is_backend_available()
…r for web_search_tool

When a search provider fails, Hermes previously returned an error
immediately — no retry with another backend.  This adds:

- search_engine parameter to web_search_tool() — model can specify
  "baidu", "serper", "ddgs", or "auto" to walk the fallback chain.
  Valid values are dynamically sourced from list_provider_names(), so
  adding a new provider automatically extends the enum — zero changes.

- web.fallback_backends config key — user-defined ordered list of
  providers to try.  If unset, all registered providers are tried
  in registration order (paid first, free last).

- _search_with_fallback() — walks the chain, skipping backends that
  are not found, not available, return errors, or return 0 results.
  Stops at first success.  Returns error trace on total failure.

This PR depends on feat/add-free-web-search-providers (PR NousResearch#53149)
which adds the 9 new providers that this chain can fall back through.
…ider priority

New subcommand: hermes tools web reorder

Shows the current web.fallback_backends list with numbered indices.
User enters a space-separated reorder (e.g. '3 1 2 4 5').
Validated for completeness (must include each number exactly once).
Writes result back to config.yaml as web.fallback_backends.

This gives users a simple way to prioritize search engines after
adding new providers via feat/add-free-web-search-providers (PR NousResearch#53149).
Copilot AI review requested due to automatic review settings June 26, 2026 16:13
@Icather
Icather marked this pull request as draft June 26, 2026 16:16
@Icather Icather closed this Jun 26, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new interactive CLI flow to reorder the web search provider fallback priority (hermes tools web reorder), and it also adds/extends the web search provider surface and fallback-chain logic in tools/web_tools.py alongside several new provider plugins.

Changes:

  • Add hermes tools web reorder subcommand to interactively reorder web.fallback_backends and persist it to config.yaml.
  • Extend tools/web_tools.py with additional provider names, generic plugin availability probing, and an "auto" fallback-chain search mode via search_engine.
  • Add new bundled web provider plugins (Serper, Baidu, Bocha, Qiniu-Baidu, SerpAPI, Jina, Google CSE) plus registry-only “unavailable” entries (Sogou, 360 Search).

Reviewed changes

Copilot reviewed 30 out of 30 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
tools/web_tools.py Adds provider candidates, plugin availability probing, and fallback-chain search behavior (search_engine="auto").
hermes_cli/tools_config.py Adds interactive reorder flow for web.fallback_backends and a display-name helper.
hermes_cli/subcommands/tools.py Registers hermes tools web reorder argparse subcommand.
plugins/web/serper/provider.py New Serper search provider implementation.
plugins/web/serper/plugin.yaml Registers Serper plugin metadata and provided provider name.
plugins/web/serper/init.py Plugin package marker for Serper.
plugins/web/baidu/provider.py New Baidu search provider implementation.
plugins/web/baidu/plugin.yaml Registers Baidu plugin metadata and provided provider name.
plugins/web/baidu/init.py Plugin package marker for Baidu.
plugins/web/bocha/provider.py New Bocha search provider implementation.
plugins/web/bocha/plugin.yaml Registers Bocha plugin metadata and provided provider name.
plugins/web/bocha/init.py Plugin package marker for Bocha.
plugins/web/qiniu-baidu/provider.py New Qiniu-Baidu search provider implementation.
plugins/web/qiniu-baidu/plugin.yaml Registers Qiniu-Baidu plugin metadata and provided provider name.
plugins/web/qiniu-baidu/init.py Plugin package marker for Qiniu-Baidu.
plugins/web/serpapi/provider.py New SerpAPI search provider implementation.
plugins/web/serpapi/plugin.yaml Registers SerpAPI plugin metadata and provided provider name.
plugins/web/serpapi/init.py Plugin package marker for SerpAPI.
plugins/web/jina/provider.py New Jina search provider implementation.
plugins/web/jina/plugin.yaml Registers Jina plugin metadata and provided provider name.
plugins/web/jina/init.py Plugin package marker for Jina.
plugins/web/google-cse/provider.py New Google CSE search provider implementation.
plugins/web/google-cse/plugin.yaml Registers Google CSE plugin metadata and provided provider name.
plugins/web/google-cse/init.py Plugin package marker for Google CSE.
plugins/web/sogou/provider.py New registry-only Sogou provider marked always-unavailable.
plugins/web/sogou/plugin.yaml Registers Sogou plugin metadata and provided provider name.
plugins/web/sogou/init.py Plugin package marker for Sogou.
plugins/web/_360_search/provider.py New registry-only 360 Search provider marked always-unavailable.
plugins/web/_360_search/plugin.yaml Registers 360 Search plugin metadata and provided provider name.
plugins/web/_360_search/init.py Plugin package marker for 360 Search.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tools/web_tools.py
Comment on lines +926 to 930
def web_search_tool(query: str, limit: int = 5, search_engine: str = "auto") -> str:
"""
Search the web for information using available search API backend.
Search the web for information using available search API backends.

This function provides a generic interface for web search that can work
Comment thread tools/web_tools.py
Comment on lines +306 to +322
cfg = _load_web_config()

# Build unique-ordered chain. Explicit backend goes first, then
# user-configured fallback list, then auto-discovered remainder.
chain: list[str] = []

primary = (cfg.get("backend") or "").lower().strip()
if primary:
chain.append(primary)

user_fbs = cfg.get("fallback_backends", [])
if isinstance(user_fbs, str):
user_fbs = [b.strip() for b in user_fbs.split(",") if b.strip()]
for b in user_fbs:
if b not in chain:
chain.append(b)

Comment thread tools/web_tools.py
Comment on lines +369 to +377
if not result.get("success"):
errors.append(f"{name}: {result.get('error', 'unknown error')}")
continue
if not len(result.get("data", {}).get("web", [])):
errors.append(f"{name}: returned 0 results")
continue

# Success — return immediately
return result, errors
Comment on lines +3431 to +3436
if set(indices) != set(range(1, len(current) + 1)):
print(color(
f" ✗ Must include each number 1–{len(current)} exactly once.",
Colors.RED,
))
return
Comment on lines +42 to +45
r.raise_for_status()
data = r.json()
raw = list(((data or {}).get("data", []) or {}).get("results", []))[:limit]
results = [
Comment thread tools/web_tools.py
Comment on lines +282 to +285
# ─── Fallback Chain & Multi-Source Search ────────────────────────────────────

def _get_valid_engine_names() -> set[str]:
"""Return the set of currently-registered search provider names.
Comment thread tools/web_tools.py
Comment on lines +1015 to +1020
# --- Auto mode: fallback chain ---
chain = _get_fallback_chain()
response_data, errors = _search_with_fallback(query, limit, chain)

if response_data is None:
summary = "; ".join(errors[-3:]) if errors else "All backends exhausted"
@alt-glitch alt-glitch added type/feature New feature or request comp/cli CLI entry point, hermes_cli/, setup wizard tool/web Web search and extraction P3 Low — cosmetic, nice to have labels Jun 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have tool/web Web search and extraction type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants