DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

Web Search — DeepSeek Harness 插件(DSH Plugin)
DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins

@ian_p/dsh-web-search

Web Search

适用于 DeepSeek Harness 的多提供商第三方网页搜索:通过可配置的提供商回退链路由原生 web_search 工具,并提供独立的提供商设置页面。

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add @ian_p/dsh-web-search@0.1.5-rc.3
README兼容性版本

兼容性与来源证明

Web Search 以 @ian_p/dsh-web-search 发布,当前版本为 0.1.5-rc.3。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
npm
Registry 更新时间
2026/9/23

版本

0.1.5-rc.3prerelease
2026/9/23

相关插件

正在加载相关插件…

最新版
0.1.5-rc.3
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
128.1 kB
文件数
9
Surface
web
许可证
MIT
发布源
npm
GitHub
★ 0
周下载
0
最近提交
2026/9/23
查看源码 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题

相关插件

继续浏览 search-research 分类下经过校验的插件。

Browser Skill Dsh Plugin@wxg-prc-cpg/browser-skill-dsh-plugin向模型提供 BrowserSkill 浏览器自动化(browser_* 工具)的 DeepSeek Harness 工具插件Weknora@wxg-prc-cpg/dsh-weknora适用于 DeepSeek Harness (dsh) 的 WeKnora 知识检索工具:通过自有知识库进行语义搜索、文档阅读以及 RAG/代理回答。Find Plugindsh-find-plugin在代理中查找 DeepSeek Harness 插件——实时搜索 GitHub 上的 dsh-plugin 主题,并按星标数排序。Dejadsh-dejaDeepSeek Harness 的 deja-vu 记忆:三十三个其他编码代理的会话历史,可搜索并在每个步骤前检索——本地索引,无需 LLM。

README

English · 简体中文

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