DSH Plugins Marketplace

DSH Plugins

Plugins

/

@deepseek-ai/dsh-web-search

F

@deepseek-ai/dsh-web-search

Manifest valid

Multi-provider third-party web search for the DeepSeek Harness: routes the native web_search tool through a configurable provider fallback chain, with an isolated provider settings page.

UI (client)hasBundlePatch

English · 简体中文

npm version MIT license DSH host version Node version

One fallback chain. Eight providers.

@ian_p/dsh-web-search is a Cordis plugin for the DeepSeek Harness that replaces the native web_search back end with a configurable, multi-provider chain. Each query walks the configured provider order and falls back to the next on failure or empty results; DuckDuckGo needs no key and closes the chain.

The browser half adds a dedicated Search providers settings page for keys, connection tests and drag-to-reorder.

Design reference: the multi-provider approach is adapted from Oh My Pi (OMP).

CapabilityWhat it changes
8 providers, one chainTavily, Brave, Exa, Firecrawl, Jina, Kagi, SearXNG, DuckDuckGo — any order, any subset.
Native web_search integrationThe patch override routes the harness's own web_search tool through this chain.
Fail-loudWith the patch not applied the native tool reports WEB_PROVIDER_AMBIGUOUS instead of silently degrading.
Host-native settings pageLocalized (en/zh) through the host locale service and styled with the host's own control contract (--dsw-* design tokens), so it follows the host language and light/dark theme.
Auditable fallbackOne host-log line per search names every provider that was skipped or failed, then the one that served.

Requirements

  • Node.js ^22.19 or >=24

  • DeepSeek Harness 0.1.5-rc.3 — this plugin hand-writes its Typert Remote descriptors, so it targets one DSH train:

    npm install --global @deepseek-ai/dsh@0.1.5-rc.3
    

    Every @deepseek-ai/dsh* service it injects (web, credentials, typert) comes from that host build, so those packages are declared as peers at the same train version rather than listed package by package. The components declared on their own:

    ComponentVersionRole
    @deepseek-ai/dsh0.1.5-rc.3Host runtime (source of every @deepseek-ai/dsh* peer)
    @deepseek-ai/cordis^4.0.2Plugin/context framework (peer + dev)
    react^18.2Browser half only (dev)
    typescript^7.0.2Type check over src/host-core.js (dev)

Installation

From npm (the package declares dsh.bundle.patch, so dsh plugin add also activates the profile bundle):

dsh plugin --profile web add @ian_p/dsh-web-search

Local development — run inside the harness source workspace; the overlay loads src/index.js directly, so no build step is needed:

pnpm dsh web --patch /path/to/dsh-web-search/patch.web.yml

web is the launcher's alias for --profile web. The overlay (patch.web.yml) inserts the plugin row and sets searchProvider: dsh-web-search on the native web row; the browser half is discovered through the dsh.client manifest plus exports["./client"].

Linked checkout (dsh plugin --profile web add "link:/path/to/checkout") loads the published shape instead, i.e. dist/ — run pnpm run build after editing src/ (pnpm install also builds it through the prepare script). A host restart is required either way.

How the chain behaves

Order comes from the settings page (drag to reorder) and is stored in the dsh-web-search/config credential record. Resolution: your ordered, non-excluded providers first, then every remaining provider in built-in order.

For each provider, in order:

  1. available() — a local check, no network call: keyed providers need a credential record, SearXNG needs its endpoint, DuckDuckGo is always available. Not available ⇒ skipped.
  2. search() with a per-provider timeout (default 60 s, timeout in the config record).
  3. Success means a non-empty answer or at least one source; then the search returns immediately — later providers are never tried. There is no racing, no merging of providers, no retry and no cache.
  4. Failure means HTTP non-2xx, invalid JSON, a thrown error, or "no renderable content"; the reason is recorded and the next provider is tried.

If every provider fails, the error names the last provider tried, and the plugin then retries the native deepseek-official provider before giving up.

Each search logs one line to the host log:

[14:32:07] [dsh-web-search] firecrawl: HTTP 429: ... → tavily: served (8 sources, 4437ms)
[14:32:09] [dsh-web-search] trying exa
[14:33:01] [dsh-web-search] brave: not configured → ... → all providers failed

A trying line with no completion line after it means that provider is still in flight (the harness log itself is not timestamped, so the plugin stamps its own lines).

Providers

IDLabelKindHow to activate
tavilyTavilyAPI keySave a Tavily API key
braveBraveAPI keySave a Brave API key
exaExaAPI keySave an Exa API key
firecrawlFirecrawlAPI keySave a Firecrawl API key
jinaJinaAPI keySave a Jina API key
kagiKagiAPI keySave a Kagi API key
searxngSearXNGEndpointSave a SearXNG instance endpoint
duckduckgoDuckDuckGoNoneAlways available (default final fallback)

Per-provider details worth knowing:

  • Tavily — results[].content is a page chunk, not a description, so the request asks for chunks_per_source: 1 (one relevant passage instead of three chunks of page chrome) and include_published_date: true.
  • Firecrawl — reports its own failures as HTTP 200 with success: false plus a warning; that is surfaced as the provider's failure reason instead of looking like an empty result set.
  • DuckDuckGo — keyless; the HTML front end is parsed, and a bot-challenge page yields zero sources so the chain keeps going.
  • SearXNG — self-hosted; week recency maps to month because the instance only understands day/month/year.

Configuration

Credentials

All provider secrets live in harness credential records under the dsh-web-search/ scope, managed from the settings page — no environment variables. (Environment-variable credential refs would shadow saved values and stop the page from working.)

  • API-key providers — an api-key record, e.g. dsh-web-search/tavily.

  • SearXNG — a grant record carrying the instance endpoint.

  • DuckDuckGo — no key.

  • Plugin config — a grant record at dsh-web-search/config:

    order: [firecrawl, tavily, brave, exa, jina, kagi, searxng, duckduckgo]
    exclude: []
    timeout: 60        # seconds, per provider
    

    The settings page writes order; exclude and timeout currently only via the record.

Settings page

Registered as the isolated settings section Search providers (id web-search-providers, order 12), separate from the native web-search config page. It lists providers in effective fallback order and lets you save or clear a key/endpoint, run a connection test, and drag the cards to reorder the chain. It talks to the host over the plugin's websearch Remote namespace (list / setKey / unsetKey / setOrder / testProvider).

The page registers en / zh dictionaries with the host locale service (sidebar label included) and paints itself with --dsw-* tokens using the host's own button, input and card geometry, so both language and theme follow the host.

What the harness receives

web_search results are shaped to match the native path:

  • Sources carry url, title?, snippet?, publishedAt? only. Snippets are cleaned (markdown headings stripped, whitespace collapsed, chunk separators removed) and held to 150 characters — the documented ceiling of the native citation excerpt — with a cut marked by ….
  • The provider's own answer (Tavily and Exa produce one) is passed as content, bounded to 400 characters, and rendered as Markdown above the source list. The native provider never sends one.
  • Truncation is the seam's decision. The plugin hands back the provider's full source list with truncated: false; the harness caps it to request.maxResults and sets truncated: true, which is what surfaces the "sources truncated" notice to both the user and the model.
  • The tool has no field for the serving provider, so it is reported on the host log instead (see above).

Architecture / project layout

dsh-web-search/
├── patch.web.yml            # --patch overlay for local development (relative ./src/index.js)
├── cordis.patch.yml         # published bundle patch (package specifier), declared via dsh.bundle.patch
├── src/                     # source of truth (never published)
│   ├── index.js             # host entry: ctx.web provider, chain orchestration, credential RPC ops
│   ├── host-core.js         # pure functions: query parsing, per-provider request building and
│   │                        # response normalization, snippet/answer policy
│   ├── remote.js            # websearch Remote namespace (WebSearchController)
│   └── client/bundle.js     # browser half: hand-written __ModuleLoader__ factory bundle (no bundler):
│                            # the settings page and its single-copy state machine
├── scripts/build.mjs        # build: clean copy of src/ → dist/ (the publishable tree)
├── dist/                    # build output — published to npm, git-ignored
├── tests/                   # 134 pure + 12 environment-dependent tests (see below)
├── docs/DESIGN.md           # host contracts this plugin depends on, and why the code is shaped this way
└── package.json             # main/exports → dist/, files: ["dist/", …], prepare builds dist/

Development / Testing

pnpm install             # installs peers/dev deps and runs `prepare`, which builds dist/
pnpm run build           # stage dist/ from src/ (clean copy, no bundler, no new dependency)
pnpm test                # 134 pure-function tests (node:test, zero dependencies)
pnpm run test:rpc        # 12 environment-dependent tests (resolves the 0.1.5-rc.3 peers)
pnpm run typecheck       # tsc -p tsconfig.types.json (JSDoc types of src/host-core.js)
pnpm run prepublishOnly  # build + both test tiers + typecheck, before a publish
TierSuiteCountWhat it covers
Puretests/host-core.test.mjs97query parsing, provider request bodies, response normalization, snippet/answer policy, credential-record helpers
Puretests/interaction.test.mjs37the settings page state machine, run against the shipped client bundle
Envtests/remote-contract.test.mjs11the Typert Remote contribution against the installed host contract
Envtests/client-bundle.smoke.mjs1bundle registration, apply(), and the injected stylesheet

src/index.js (the host entry: transport, chain, credential ops, ctx.web injection) has no test coverage — it needs the harness runtime; docs/DESIGN.md records what that leaves unpinned.

License

MIT © ForeverYoungPp

Comments

Loading…

Similar plugins

dsh-web-search-plugin

by X-C1811

Tavily web-search provider for DeepSeek Harness (ctx.web). Keyless or API-key modes with a configurable UI card; provider framework designed to be extended to more search APIs.

Tools & CapabilitiesManifest valid

★ 2

↓ 122/wk

MIT

JavaScript

Sep 16, 2026

dsh plugin --profile web add dsh-web-search-plugin

by cinob

🌐 Multi-provider web search plugin for DeepSeek Harness: Zero-key Bing/Baidu direct search, free-tier APIs (Tavily/Brave/Serper/Bocha), SearXNG token auth, auto-fallback, and a built-in Web Settings

Terminal & ClientsManifest valid

★ 7

↓ 480/wk

MIT

JavaScript

Aug 26, 2026

dsh plugin --profile web add dsh-web-search-multi

by abcdream-Lary

DeepSeek Harness (DSH) 的多提供商网页搜索和页面获取插件:AnySearch、Bing、DuckDuckGo、Tavily、Exa

Terminal & ClientsTools & CapabilitiesManifest valid

★ 2

↓ 56/wk

MIT

JavaScript

Aug 22, 2026

dsh plugin --profile web add dshsearch-multi

by gxpppp

Replace dsh's built-in web search with search MCP servers (Tavily/Brave/Exa/Perplexity/DuckDuckGo/custom), configured from the web Settings page. Disables the built-in DeepSeek search provider while e

Models & ProvidersTools & CapabilitiesTerminal & ClientsManifest valid

★ 10

MIT

JavaScript

Aug 30, 2026

dsh plugin --profile web add dsh-search-mcp

by ChrisDeadman

Brave Search API-backed web search provider for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (`dsh`)

Tools & CapabilitiesManifest valid

★ 0

MIT

JavaScript

Sep 4, 2026

dsh plugin --profile web add @deads-inc/dsh-web-search-brave

by A3Boy

Multi-provider Web Search & Fetch for DeepSeek Harness — 8 deeply adapted providers, SearchHints, resilient fallback, and native X / Xiaohongshu retrieval.

Models & ProvidersTools & CapabilitiesTerminal & ClientsWorkflow & AutomationManifest valid

★ 30

MIT

JavaScript

Sep 3, 2026

dsh plugin --profile web add dsh-web-tools