DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

XGrin /

XGrin/dsh-search-router

Verified

A tiny DeepSeek Harness (DSH) plugin

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@bd167289

dsh-search-router

English · 中文

A tiny DeepSeek Harness (DSH) plugin: one native WebSearchProvider registered into ctx.web, forwarding every web_search call to a search backend you choose — with sequential fallback when one fails. The model keeps seeing the same web_search tool; no new tools, no MCP, no reranking, no caching.

DSH Agent → web_search → ctx.web → dsh-search-router → Exa / Tavily / Brave / SearXNG

Supported providers

Provider Credential Endpoint
Exa EXA_API_KEY https://api.exa.ai
Tavily TAVILY_API_KEY https://api.tavily.com
Brave BRAVE_SEARCH_API_KEY https://api.search.brave.com
SearXNG none (self-hosted) SEARXNG_BASE_URL

SearXNG keeps the router fully self-hostable — no commercial API needed. The instance must enable the json output format (search.formats in its settings.yml). Endpoints of the three commercial providers can be overridden per provider (see the full schema below).

Install

dsh plugin --profile web add github:XGrin/dsh-search-router
dsh web

Or clone and link locally (for development):

git clone https://github.com/XGrin/dsh-search-router.git
dsh plugin --profile web add link:/path/to/dsh-search-router

The composition patch points the web seam at the router, disables the built-in DeepSeek search provider, and re-enables the web_search tool in the web profile. Uninstall (dsh plugin --profile web remove dsh-search-router) restores the original composition.

Configure

Two ways, targeting the same knobs — the GUI wins per field, and a GUI reset re-inherits the composition value. With zero configuration the router auto-detects every provider whose key or endpoint is ambient, in canonical order: exa → tavily → brave → searxng.

In the app

Settings → Plugins → Plugin configuration shows a "Search router" card: one row per active provider, numbered by fallback priority and draggable to reorder (also keyboard-reorderable), an inline editor per provider, an add-provider flow, and an Advanced fold (timeout, empty-results policy). Every change applies live — no restart.

API keys entered here persist in the settings document as secrets and override the environment variables; clearing a stored key falls back to EXA_API_KEY / TAVILY_API_KEY / BRAVE_SEARCH_API_KEY.

In the composition

The profile's own patch layer — $DSH_HOME/profiles/web/cordis.patch.yml (create it if absent). A patch replaces the row's whole config, so state the complete block. Two examples:

# Tavily, falling back to a self-hosted SearXNG
- id: search-router
  config:
    order: [tavily, searxng]
    providers:
      tavily: { apiKeyEnv: TAVILY_API_KEY }
      searxng: { baseUrl: https://search.example.com }

# SearXNG only — no commercial keys anywhere
- id: search-router
  config:
    provider: searxng
    providers:
      searxng: { baseUrl: http://127.0.0.1:8888 }

Full schema:

- id: search-router
  config:
    provider: exa                  # single-provider mode (XOR with order)
    order: [exa, tavily, searxng]  # fallback-chain mode
    timeoutMs: 10000               # per-provider timeout (default 10000)
    emptyResultsFallback: true     # 0-result success counts as failure (default true)
    providers:
      exa:    { apiKey: …, apiKeyEnv: EXA_API_KEY, baseURL: … }
      tavily: { apiKey: …, apiKeyEnv: TAVILY_API_KEY, baseURL: … }
      brave:  { apiKey: …, apiKeyEnv: BRAVE_SEARCH_API_KEY, baseURL: … }
      searxng: { baseUrl: …, baseUrlEnv: SEARXNG_BASE_URL }

Prefer apiKeyEnv over a literal apiKey in files you might commit.

Fallback

A provider counts as failed on network errors, timeouts, any non-2xx status, unparseable responses — and by default on empty results (emptyResultsFallback: false to change). The router walks the chain in order and returns the first success; the model never sees the earlier failures. If every provider fails, web_search throws one aggregated, key-free error:

search-router: all configured search providers failed:
- exa: HTTP 429
- tavily: timeout after 10000ms
- searxng: HTTP 503

Development

node test/integration.mjs /path/to/a/dsh/installation/node_modules   # router vs. the real seam, mocked providers
node test/client-smoke.mjs                                          # browser bundle, the way the shell loads it

MIT.

—/ 5

No ratings yet

Verified DSH bundle

Commit bd167289ebbf

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout