DeepSeek Harness Plugin Hub

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

探索

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

社区

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

相关链接

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

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

DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins
B

dsh-balanced-search

Balanced Search

面向 DeepSeek Harness 的均衡网页搜索:Keenable / Exa / Tavily / Firecrawl / AnySearch / TinyFish 轮询执行搜索和抓取,并自动故障转移。注册 balanced_search / balanced_fetch 作为 dsh 工具,通过 ctx.web 接口接管内置的 web_search / web_fetch,并由客户端部分使用官方风格卡片(附加“balanced”后缀)呈现这两个工具。

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

npx -y @deepseek-ai/dsh plugin --profile web add github:tianmingwan/dsh-balanced-search#1f1bcb27fb8154c58f4b3190c00050efa09cb014
README兼容性版本

兼容性与来源证明

Balanced Search 以 dsh-balanced-search 发布,当前版本为 0.5.0。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
github
Registry 更新时间
2026/10/22

版本

0.5.0stable
2026/10/22
0.2.0stable
2026/9/15

相关插件

正在加载相关插件…

最新版
0.5.0
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
未提供
文件数
未提供
Surface
web
许可证
MIT
发布源
github
GitHub
★ 5
周下载
0
最近提交
2026/10/22
查看源码 ↗
README Badge

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

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

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

认领这个 Plugin →
报告问题

相关插件

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

MarketdshmarketDeepSeek Harness 内的可视化插件市场——浏览、搜索并一键安装社区插件。· DSH 可视化插件市场:浏览、搜索并一键安装社区插件。Free Searchdsh-free-searchDeepSeek Harness 的免费网页搜索:27 个引擎(Bing/DuckDuckGo/AnySearch/SearXNG/Exa/Tavily/Keenable/Firecrawl/Parallel/You.com 无需密钥;通过 MCP 支持 Zhihu 全局/站内搜索,以及 Perplexity/SerpBase/DeepSeek(官方 + 原生工具/搜索)/Baidu/Kimi/Aliyun/Douba)Ab Wechat Scrapedsh-ab-wechat-scrape--- description: "树外 wechat_scrape 工具:获取微信公众号文章,过滤推广区块,并将每篇文章保存为 Markdown 文件,供此机器的 dsh 配置文件维护者使用。" kind: "package-reference" ---Ab Market Researchdsh-ab-market-research一个树外 DeepSeek Harness 插件:将 trade_search 工具(多轮扩展方面的查询规划、出版商级别排序、来源多样性、JSON 快照)及其浏览器卡片集成在一个包中。

README

dsh-balanced-search

English: A balanced web search plugin / MCP server that round-robins across Keenable (Keen Search) / Exa / Tavily / Firecrawl / AnySearch / TinyFish — six independent search & fetch backends — and automatically fails over to the next provider. Returns normalized titles, links, and content summaries.

中文: 均衡搜索插件 / MCP 服务器:把 Keenable(Keen Search)/ Exa / Tavily / Firecrawl / AnySearch / TinyFish 六个搜索 / 抓取 API 轮流调用(round-robin),某个服务失败时自动切换下一个,统一返回标题 / 链接 / 摘要。

This repository provides two forms / 本仓库同时提供两种形态:

  1. DeepSeek Harness native plugin (recommended) / dsh 原生插件(推荐) — registers balanced_search / balanced_fetch as dsh tools and automatically takes over the built-in web_search / web_fetch, no Python required. / 既注册 balanced_search / balanced_fetch 两个 dsh 工具,同时自动接管内置的 web_search / web_fetch,无需 Python。
  2. Generic MCP server / 通用 MCP 服务器 — exposes search / fetch over stdio via server.py for any MCP client. / 通过 server.py 以 stdio 方式暴露 search / fetch,可供任意 MCP 客户端使用。

Features / 功能

  • Search the web and return titles, links, and content summaries. / 搜索网页,返回标题、链接和内容摘要。
  • Fetch a URL and return clean markdown text. / 抓取指定 URL 的网页正文,返回 clean markdown。
  • Round-robin across six providers — all ordinary REST APIs — with automatic failover. / 六个服务(均为 REST API)轮流调用,单个服务失败时自动切换下一个。
  • Configure API keys via environment variables; providers without a key are skipped. / 通过环境变量配置 API key;未配置的服务不会启用。
  • Takes over the built-in web_search / web_fetch automatically — the bundle pins dsh's web row to this plugin's balanced provider, so no manual profile edit is needed. / 自动接管内置的 web_search / web_fetch:bundle 层把 dsh 的 web 行钉到本插件的 balanced provider,无需手工改任何配置。
  • Fetch happens server-side, at the vendor — so it also works where the shipped local http fetch provider cannot. See Configuration Notes. / 抓取在厂商服务端完成,因此在 dsh 自带本地抓取 provider 无法工作的环境下依然可用,见配置说明。

Environment Variables / 环境变量

Configure at least one search provider API key / 至少配置一个搜索服务的 API key:

KEENABLE_API_KEY=...
EXA_API_KEY=...
TAVILY_API_KEY=...
FIRECRAWL_API_KEY=...
ANYSEARCH_API_KEY=...
TINYFISH_API_KEY=...

👉 Where to register and get each key (all six) — sign-up links, where the key lives in each dashboard, free quotas, and what one call costs: API_KEYS.md. 六家的注册入口、key 在各家后台的哪个页面、免费额度、以及单次调用消耗,见 API_KEYS.md。

ProviderSign up / 注册Env varFree tier / 免费额度Docs / 文档
Keenablehttps://app.keenable.ai/loginKEENABLE_API_KEY100,000 requests / monthhttps://docs.keenable.ai
Exahttps://dashboard.exa.ai/onboarding-guestEXA_API_KEY$20 on sign-up + $10 / monthhttps://docs.exa.ai
Tavilyhttps://app.tavily.comTAVILY_API_KEY1,000 credits / monthhttps://docs.tavily.com
Firecrawlhttps://www.firecrawl.dev/signinFIRECRAWL_API_KEY1,000 credits / month (≈500 searches or 1,000 page fetches; 10 req/min) / 1,000 credits / 月(≈500 次搜索或 1,000 页抓取,10 req/min)https://docs.firecrawl.dev
AnySearchhttps://www.anysearch.com/loginANYSEARCH_API_KEY1,000 requests / day (search + extract share it), 20 QPS per key; hard cap of 10 results and no recency filter / 1,000 请求/天(search 与 extract 共用),每 key 20 QPS;结果硬上限 10 条、不支持时间过滤https://anysearch.com/docs/api-endpoints
TinyFishhttps://agent.tinyfish.ai/api-keysTINYFISH_API_KEYSearch & Fetch are $0 — 12,000 searches / day (500 / hour, 30 / min) plus 1,000 fetched URLs / day / 搜索与抓取均为 $0——12,000 次搜索/天(500/小时、30/分),抓取 1,000 个 URL/天https://docs.tinyfish.ai

Free-tier figures are as of 2026-10-22 and change often — always check the vendor's pricing page. / 以上免费额度为 2026-10-22 的快照,各家随时可能调整,请以官方定价页为准。

The dsh native plugin reads process environment variables directly. The Python MCP server also loads a .env file in the same directory. / dsh 原生插件直接读取进程环境变量;Python MCP 服务器还会自动读取同目录下的 .env 文件。

Directory Structure / 目录结构

File / 文件Description / 说明
index.jsdsh native plugin entry; registers balanced_search / balanced_fetch and the ctx.web provider balanced / dsh 原生插件入口:注册两个工具,并向 ctx.web 注册 balanced provider
cordis.patch.ymldsh bundle config layer; inserts the plugin and pins the web row to the balanced provider / dsh bundle 配置层:插入插件,并把 web 行钉到 balanced provider
package.jsondsh bundle manifest / dsh bundle 声明
server.pyGeneric MCP server (stdio); exposes search / fetch / 通用 MCP server
providers.pyPython providers + round-robin / failover / Python 版 API 客户端与轮换
scripts/probe.mjsProbe a single vendor in isolation through the real plugin code / 通过真实插件代码单独探测试某一家厂商
requirements.txtPython MCP server dependencies / Python MCP 服务器依赖
.env.exampleTemplate for all six API keys (copy to .env) / 六个 API key 的配置模板(复制为 .env)
API_KEYS.mdWhere to register the six APIs and get keys / 六个 API 的注册与 key 领取说明
.gitignoreExcludes .env, virtualenvs, caches / 排除本地敏感与缓存文件

Install as a dsh Plugin / 安装为 dsh 插件

Requirements / 要求:DeepSeek Harness (dsh) installed, Node.js ≥ 20.

dsh plugin --profile web add github:tianmingwan/dsh-balanced-search

After restarting dsh --profile web / 重启 dsh --profile web 之后:

  • Two extra tools appear / 新增两个工具:balanced_search、balanced_fetch
  • The built-in web_search / web_fetch are taken over automatically — no manual profile edit / 内置的 web_search / web_fetch 被自动接管,无需手工修改 profile 配置

No Python dependencies required / 无需安装 Python 依赖。

How the takeover works / 接管是怎么实现的

package.json declares dsh.bundle.patch, which makes this package a bundle layer. Installing it composes cordis.patch.yml on top of the bundles listed before it — notably @deepseek-ai/dsh-base, which mounts the web row — and that layer pins the row's providers:

- id: web
  name: '@deepseek-ai/dsh-web'
  config:
    searchProvider: balanced
    fetchProvider: balanced

index.js registers a single provider with id balanced into both the seam's search and fetch registries, so the pin covers both capabilities. (A patch replaces the targeted row's whole config rather than merging, which is why both fields are restated.)

Key requirement / key 要求

The takeover needs at least one of KEENABLE_API_KEY / EXA_API_KEY / TAVILY_API_KEY / FIRECRAWL_API_KEY / ANYSEARCH_API_KEY / TINYFISH_API_KEY. With none set, the balanced provider reports itself unavailable and the built-in tools fail with WEB_PROVIDER_CONFIGURED_UNAVAILABLE naming balanced. / 接管需要至少配置一个 key(六种任选其一);一个都没有时,balanced provider 会报告不可用,内置工具会以 WEB_PROVIDER_CONFIGURED_UNAVAILABLE 失败。

Opting out / 取消接管

A user's own ~/.dsh/profiles/<profile>/cordis.patch.yml is applied after every bundle layer, so the pin can be overridden or removed there — restoring dsh's shipped deepseek-official search / http fetch while keeping the two extra tools. / 用户自己的 cordis.patch.yml 在所有 bundle 层之后应用,因此可以在那里覆盖或删除这两行,恢复 dsh 自带的 provider,同时保留两个额外工具。

Use as a Generic MCP Server / 作为通用 MCP 服务器使用

Install / 安装

python -m venv .venv
# Windows
.venv\Scripts\python.exe -m pip install -r requirements.txt
# Linux / macOS
.venv/bin/python -m pip install -r requirements.txt

Run / 运行

# stdio mode for MCP clients / stdio 模式,供 MCP 客户端连接
python server.py
# or use the virtualenv Python / 或使用虚拟环境中的 Python
.venv\Scripts\python.exe server.py   # Windows
.venv/bin/python server.py           # Linux / macOS

MCP Client Example / MCP 客户端接入示例

{
  "mcpServers": {
    "balanced-search": {
      "command": "/absolute/path/to/.venv/bin/python",
      "args": ["/absolute/path/to/server.py"],
      "env": {
        "KEENABLE_API_KEY": "...",
        "EXA_API_KEY": "...",
        "TAVILY_API_KEY": "...",
        "FIRECRAWL_API_KEY": "...",
        "ANYSEARCH_API_KEY": "...",
        "TINYFISH_API_KEY": "..."
      }
    }
  }
}

Tool Usage / 工具用法

dsh Native Tools / dsh 原生工具

  • balanced_search — parameters / 参数:query / max_results / time_range
  • balanced_fetch — parameters / 参数:url / max_chars / live

Built-in Tools after Takeover / 接管后的内置工具

These keep dsh's own schemas — this plugin supplies the retrieval backend only, so their parameters are fixed by dsh, not by this plugin. / 它们沿用 dsh 自己的工具签名:本插件只提供检索后端,参数由 dsh 决定。

web_searchbalanced_search
Query / 查询queries: string[] (up to 4 per call / 一次最多 4 条)query: string
Result count / 条数deployment config (default 8) / 部署配置,默认 8max_results 1–20
Time range / 时间范围✗ (deferred by the seam / seam 明确暂不支持)time_range
  • web_fetch — parameter / 参数:url only / 仅 url。No max_chars / live; timeout and output cap are deployment policy / 没有这两个参数,超时与输出上限属部署策略。
  • balanced_fetch — keeps / 保留 max_chars / live.

The two surfaces complement each other / 两套接口互补:use web_search / web_fetch for dsh-native naming and multi-query, and balanced_search / balanced_fetch when you need time_range, live, or max_chars.

MCP Tools / MCP 工具

  • search — parameters / 参数:query / max_results / time_range
  • fetch — parameters / 参数:url / max_chars / live

Parameter Reference / 参数说明

  • query (required / 必填): Search keyword or natural language question / 搜索关键词或自然语言问题
  • max_results: 1–20, default 8 / 1–20,默认 8
  • time_range: day / week / month / year (native for Tavily; Exa maps to startPublishedDate; Keenable maps to published_after; Firecrawl maps to a relative recency window (tbs); TinyFish maps to recency_minutes; AnySearch has no recency parameter at all, so it is skipped for time-filtered searches whenever a capable vendor is configured) / (Tavily 原生;Exa 映射为 startPublishedDate;Keenable 映射为 published_after;Firecrawl 映射为回溯时间窗口(tbs);TinyFish 映射为 recency_minutes;AnySearch 完全没有 recency 参数,因此只要池子里有支持回溯的厂商,带时间过滤的搜索就不会发给它)
  • max_chars: Maximum characters to return, default 30000, max 50000. AnySearch and TinyFish have no length parameter, so the cap is applied client-side (AnySearch's server already caps near 50k) / 抓取内容最大字符数,默认 30000,上限 50000。AnySearch 与 TinyFish 没有长度参数,截断在客户端完成(AnySearch 服务端正文本来就以约 50k 封顶)
  • live: Fetch live from the source (bypass index/cache), default false. Honoured by Keenable, Exa, Firecrawl (maxAge: 0 forces an origin re-scrape) and TinyFish (ttl: 0); Tavily's extract API and AnySearch's extract have no equivalent control. / 是否实时从源站抓取(绕过索引/缓存),默认 false。Keenable、Exa、Firecrawl(Firecrawl 传 maxAge: 0 强制回源)与 TinyFish(ttl: 0)支持;Tavily 的 extract 与 AnySearch 的 extract 没有对应开关。

Provider differences / 各家能力差异

ProviderSearch / 搜索Fetch / 抓取Notable limits / 需要注意
KeenableRESTRESTsupports time_range and live / 支持时间范围与实时抓取
ExaRESTRESTsupports time_range (startPublishedDate) and live / 支持时间范围与实时抓取
TavilyRESTRESTnative time_range; no live control / 原生时间范围;无实时开关
FirecrawlRESTRESTboth capabilities supported; fetch serves a cached copy up to 2 days old unless live=true (then maxAge: 0, slower and more failure-prone); free tier is capped at 10 req/min, so it is one pool member rather than the main engine; the only backend that reports the origin page's HTTP status (see below) / 搜索与抓取都支持;抓取默认走最长 2 天的缓存,live=true 时传 maxAge: 0 回源(更慢、更容易失败);免费档硬限 10 req/min,因此它是池中的一员而非主力;也是唯一会返回原页面 HTTP 状态码的后端(见下)
AnySearchRESTREST (extract)hard caps max_results at 10 (silently truncates more) and has no recency parameter, so time_range searches skip it; extract takes exactly {"url": …}, returns ~50k chars of Markdown; search and extract share 1,000 requests/day / max_results 硬上限 10(超过静默截断)且没有 recency 参数,带 time_range 的搜索会跳过它;extract 请求体严格只有 {"url": …},返回约 50k 字符的 Markdown;search 与 extract 共用每日 1,000 次请求
TinyFishREST (GET)RESTauth uses X-API-Key (not Bearer); no max_results, exactly 10 results per page, so max_results > 10 costs a second page=1 request merged by URL; recency_minutes supports all four time ranges; both search and fetch are free / 鉴权用 X-API-Key(不是 Bearer);没有 max_results 参数,每页固定 10 条,max_results > 10 时要再发一次 page=1 并按 URL 去重合并;recency_minutes 支持全部四种时间范围;搜索与抓取都免费

On the fetch side, Firecrawl is the only backend that reports the origin page's own status (it is a scrape, not an index extraction); the other five extract server-side and never see it. / 抓取侧只有 Firecrawl 会返回原页面状态码(它是真实抓取而非索引抽取);其余五家都是服务端抽取、看不到原页面状态。

Search response / 搜索返回 JSON:

{
  "provider": "keenable|exa|tavily|firecrawl|anysearch|tinyfish",
  "count": 1,
  "results": [
    {"title": "...", "url": "...", "content": "...", "published_at": "...", "score": 0.5}
  ]
}

Fetch response / 抓取返回 JSON:

{
  "provider": "keenable|exa|tavily|firecrawl|anysearch|tinyfish",
  "result": {"url": "...", "title": "...", "content": "..."}
}

The result of a Firecrawl fetch may also carry statusCode — the origin page's own HTTP status. / Firecrawl 的抓取结果还可能带 statusCode,即原页面的 HTTP 状态码。

Free-tier parameter design / 免费档参数设计

Every default in the adapters is chosen so the pool stays inside the free plans and never spends quota on a parameter that does not change the answer. / 适配层的每个默认参数都以"不超免费额度、不为不改变结果的东西付费"为准。

VendorCost-safe choice / 成本安全的选择Why / 原因
Keenableone request per search or fetch, realtime mode, no extra optionsa flat 100,000 requests/month: one call is one unit / 固定 100,000 请求/月,一次调用就是一个单位
Exatype: auto, 3,000-char text budget per resultthe cheapest search type, and card snippets do not need whole pages / 最便宜的搜索类型;卡片摘要不需要整页正文
Tavilyadvanced depth kept on purpose2 credits/search buys materially better research results, and the cost is spread over six quotas / 2 credits/次换来更好的研究结果,且成本摊到六份额度上
Firecrawlno scrapeOptions on /search, sources: ['web'], caller's exact result count as limitscraping each result would cost 1 credit per result on top of 2 credits per 10 results / 逐条抓取会在"2 credits / 10 条"之外再按条计费(每条 1 credit)
AnySearchmax_results clamped to 10 and kept out of time_range searchesthe server silently truncates anything above 10, and there is no recency field at all — returning unfiltered results for a filtered request would silently break the caller's contract / 服务端对超过 10 条静默截断;而且根本没有 recency 字段——用未过滤结果冒充过滤结果会悄悄破坏调用方契约
TinyFishnormally one request; a second page=1 only when max_results > 10, merged by URL; live → ttl: 0exactly 10 results per page with no max_results parameter, and the free plan is $0, so the extra page costs quota rather than money / 每页固定 10 条且没有 max_results 参数;免费档 $0,多翻一页占的是额度而不是钱

Two accounting notes / 两个额度记账要点:

  • AnySearch's 1,000 requests/day is shared by search and extract, so every fetch spends the same budget as a search; that is another reason the vendor is one pool member rather than the workhorse. / AnySearch 的每日 1,000 次请求由 search 与 extract 共用,所以每次抓取消耗的额度和搜索一样——这也是它只做池中一员而非主力的原因。
  • TinyFish's search and fetch allowances are counted separately (12,000 searches/day vs 1,000 URLs/day), and neither draws on a wallet balance. / TinyFish 的搜索与抓取额度分开计(12,000 次搜索/天 与 1,000 个 URL/天),两者都不扣 wallet 余额。

Why a cooldown exists / 为什么需要 cooldown:a spent daily/monthly quota or a revoked key fails the same way on every rotation, so retrying it every Nth call only adds latency. auth failures park the vendor for 30 minutes, quota for 20 minutes (a daily plan may reset sooner, and the user may top up mid-session), and rate for 30 seconds. A cooldown never empties the pool — when everything is cooling down, all vendors are tried again. / 额度用尽或被吊销的 key 每次轮换都会以同样方式失败,每 N 次调用重试一次只会增加延迟。auth 失败停放 30 分钟、quota 停放 20 分钟(日额度可能更早重置,用户也可能中途充值)、rate 只停 30 秒。cooldown 不会让池子变空:全部在冷却时仍会重试所有厂商。

Configuration Notes / 配置说明

  • Change keys / 换 key:dsh plugin uses environment variables; MCP server uses .env or client env injection.
  • Failover strategy / 轮换策略:Balancer (currently round-robin + failover; can be changed to weighted or health-aware). Search and fetch advance independent cursors, so a fetch does not shift the next search's starting provider. A failed vendor can also be parked briefly by kind — auth 30 min, quota 20 min, rate 30 s — so a dry or revoked key is not retried on every rotation; if every vendor is cooling down they are all tried anyway, so a cooldown never turns into "no provider configured". / 搜索与抓取各自独立推进游标,一次抓取不会改变下次搜索的起点。失败的厂商还会按类别被短暂停放——auth 30 分钟、quota 20 分钟、rate 30 秒——避免对着已耗尽或已吊销的 key 每次轮换都重试;全部都在冷却时会照常重试全池,所以 cooldown 不会变成"没有可用 provider"。
  • time_range routing / 时间过滤路由:providers that cannot filter by recency (supports_time_range = False, currently AnySearch) are left out of a time-filtered search as long as at least one capable vendor is configured — returning unfiltered results for a filtered request would silently break the caller's contract. The whole pool is used only when nobody can honour the filter. / 不支持时间过滤的厂商(supports_time_range = False,目前是 AnySearch)在池子里还有能过滤的厂商时不会参与带 time_range 的搜索——用未过滤结果冒充过滤结果会悄悄破坏调用方的契约;只有当全池都不支持时才会退回整个池子。
  • Add a provider / 新增服务:there are six today. JS: add a Provider class in index.js and register it in buildBalancer(); Python: add a SearchProvider subclass in providers.py and register it in build_balancer(). Set supports_time_range = False on the class (or supportsTimeRange = false in JS) when the vendor has no recency parameter. Providers without a key are skipped, so adding one never changes behaviour for existing users. / 目前有六个。JS 侧在 index.js 里加一个 Provider 类并注册到 buildBalancer();Python 侧在 providers.py 里加一个 SearchProvider 子类并注册到 build_balancer()。厂商没有回溯参数时,在类上标 supports_time_range = False(JS 为 supportsTimeRange = false)。没有 key 的 provider 会被跳过,因此新增一家不会影响既有用户。
  • Round-robin cost / 轮询成本:calls are spread across all six quotas, so no single free tier is the bottleneck. / 调用现在摊到六个免费额度上,不再压在单一额度上。
  • Server-side fetch / 服务端抓取:the fetch call is made by Keenable / Exa / Tavily / Firecrawl / AnySearch / TinyFish, so the page is retrieved from their network, not yours. This is why fetching still works when the local machine's DNS maps hosts into private or benchmark ranges — for example a Clash / mihomo TUN in mode answering with addresses — where dsh's shipped local fetch provider refuses with . / 抓取由 Keenable / Exa / Tavily / Firecrawl / AnySearch / TinyFish 发起,网页是在里取的。因此当本机 DNS 把域名解析到私有或保留网段(例如 Clash / mihomo TUN 的 模式返回 地址)时,抓取依然可用;而 dsh 自带的本地 provider 会以 拒绝。

License

MIT

fake-ip
198.18.0.0/15
http
resolves to a non-public IP address
它们的网络
fake-ip
198.18.0.0/15
http
resolves to a non-public IP address
  • Reporting a fetch status / 关于抓取状态码:the seam's WebFetchResult requires a statusCode. Firecrawl reports the origin page's own status; the other five vendors extract server-side without exposing it, so the seam reports 200 for a successful extraction and infers truncated from whether the body reached its cap. The plugin's own tool keeps the field out of its JSON instead, and its card falls back to HTTP 200 for the same reason the seam does. / seam 要求返回 statusCode。Firecrawl 会返回原页面状态码;其余五家都是服务端抽取、不暴露原页面状态,因此 seam 侧抽取成功即记为 200,truncated 按正文是否触顶推断。插件自己的工具则是在 JSON 里省略该字段,卡片出于同样理由回退显示 HTTP 200。
  • Timeout budgets / 超时预算:每个 provider 有统一的单次请求预算(JS 插件为 20 s 搜索 / 45 s 抓取;Python MCP 版沿用统一的 30 s 客户端超时);六家都是 REST 服务,Firecrawl 也用这个通用预算、没有专属值。插件自己的 balanced_search / balanced_fetch 工具预算是 60 s,所以一次慢调用被放弃后仍有时间切到下一家 —— 但接管的 web_search / web_fetch 用的是 dsh 自己的预算:本 profile 里 searchTimeoutMs: 60000,而 fetchTimeoutMs 未配置、取 dsh 默认的 30 s。想在接管路径上保留同样的 failover 余量,就在自己的 profile cordis.patch.yml 里给 tool-web 行补 fetchTimeoutMs(补丁会整行替换 config,所以 fetch: true 与 searchTimeoutMs 要一起写上)。 / per-provider budgets are a uniform 20 s search / 45 s fetch in the JS plugin (the Python MCP server keeps a single 30 s client timeout); all six backends are REST services and Firecrawl uses that generic budget with no dedicated value. The plugin's own tools budget 60 s, so a slow vendor is abandoned with time left to try the next one; the taken-over web_search / web_fetch use dsh's own budgets instead — this profile sets searchTimeoutMs: 60000 and leaves fetchTimeoutMs at dsh's 30 s default. To keep the same failover headroom on the takeover path, add fetchTimeoutMs to the tool-web row in your profile's cordis.patch.yml (a patch replaces the whole config, so restate fetch: true and searchTimeoutMs too).