dsh-web-tool-provider:为 web_search / web_fetch 统一 Tavily、Exa、Firecrawl 后端

前言

在 DeepSeek Harness(DSH)里做联网智能体时,web_search 和 web_fetch 往往要对接 Tavily、Exa、Firecrawl 等不同厂商:各家 API 形状、密钥管理和降级策略都不一致,换一家后端就要改配置或改代码。社区插件 dsh-web-tool-provider(维护者 nhhc-lxr,分类:联网工具)在 Harness 的 ctx.web 契约与三家厂商之间做归一化中间层:搜索和抓取可以分别选后端,密钥走设置页与凭据库,必要时还能在无密钥或厂商失败时降级到本地 HTTP 抓取。

这是什么

dsh-web-tool-provider 是 DeepSeek Harness 的 web_search / web_fetch 与 Tavily / Exa / Firecrawl 之间的归一化中间层。Harness 侧只面对统一的 ctx.web 契约;具体请求参数转换、输出形状对齐、错误码映射由本插件完成。

web_search ─┐                          ┌─ tavily
            ├─ ctx.web 统一契约 ───────┤
web_fetch  ─┘   (本插件负责转换)        └─ exa / firecrawl

仓库:https://github.com/nhhc-lxr/dsh-web-tool-provider
目录页:https://www.skillhub.cn/plugins/nhhc-lxr/dsh-web-tool-provider
许可证:MIT(见仓库 README)。

核心功能

输入与输出归一

  • 输入归一:通用层只暴露域名白名单 / 黑名单;每次搜索固定 5 条结果;深度、主题、格式、地区等厂商参数由插件内部默认值决定,设置页不逐项暴露。
  • 输出归一:统一的 source 结构、统一的日期格式(publishedAt 为 YYYY-MM-DD)、统一的错误码;厂商侧的 author、warnings、failed_results 等折进同一套字段。
  • 不向厂商索要「现成答案」:Tavily 的 include_answer 与 Exa 的 contents.highlights 均关闭;content 字段只承载降级说明,正文一律通过 web_fetch 获取。

输出契约(TypeScript 形状,见 README):

SearchResult = { content?: string; sources: { url; title?; snippet?; publishedAt? }[]; truncated: boolean }
FetchResult  = { url: string; statusCode: number; body: { kind: 'text' | 'html'; content: string }; truncated: boolean }

snippet 单行且不超过 400 字;Exa 在不请求 contents 时只有链接、标题和日期,没有 snippet。

设置页:后端可独立切换

路径:Settings → Plugins → 网页工具后端。一页三块:web_search 与 web_fetch 各有一个后端下拉(可分别选 Tavily / Exa / Firecrawl),以及三家 API 密钥区。

两个下拉改动即存,没有单独的保存按钮。密钥需显式保存(避免输一半写入凭据库):已配置的行隐藏输入框,点铅笔才展开;输入框左侧会显示剩余额度(直连厂商接口查询,不经 ctx.web)。Exa 无余额接口,页面显示「无额度接口」。

密钥解析顺序:插件配置里的字面量 → 凭据库 → 环境变量(TAVILY_API_KEY / EXA_API_KEY / FIRECRAWL_API_KEY),每次调用重新解析;字面量密钥不会写入状态文件。

可选 YAML 与状态文件

界面主要改后端与通用选项;更细的默认值可从 profile 的 cordis.patch.yml 读取,包括 search / fetch 的 backend、域名列表、fallbackToHttp,以及 providers.tavily / providers.exa / providers.firecrawl 下的 baseURL、timeoutMs、maxChars 与各厂商专有字段等(完整字段表见 GitHub README)。

后端与通用选项还保存在插件自管状态文件 <profile>/.web-tool-provider/state.json(回退 $DSH_HOME、~/.dsh);状态文件优先于 Config。

运行行为要点

  • web_search 多 query = 多次厂商调用(工具层并发后合并)。
  • 抓取结果一律标为 text(三家返回 markdown/文本)。
  • 抓取降级:厂商报错、额度、无密钥、空正文、超时等 → 可本地 HTTP 抓取并附带 notice;目标页 4xx 不降级;abort 不降级。本地抓取仅有协议白名单、内网/回环拦截、重定向校验与字节上限,没有官方 dsh-web-fetch-http 的 DNS 公网校验与连接钉扎;需要那层保护时可关闭 fallbackToHttp。
  • 搜索不降级:选中后端未配密钥则报 WEB_PROVIDER_CREDENTIAL_MISSING。

各后端默认请求参数(可在 YAML 覆盖)见 README 表格,例如 Tavily 搜索 max_results=5,Firecrawl 抓取 /v2/scrape(markdown、onlyMainContent、48h 缓存)等。

安装与启用

在已配置 web profile 的 DSH 环境中,使用 README 给出的命令安装:

dsh plugin --profile web add github:nhhc-lxr/dsh-web-tool-provider

安装后打开 Settings → Plugins → 网页工具后端,为将要使用的厂商配置 API 密钥,并按需分别选择 web_search 与 web_fetch 的后端。

插件以当前 DSH 进程权限运行;安装前请自行审阅仓库源码与 MIT 许可证。改插件代码后需重启一次 Harness 才会加载新的 host 实现;设置页刷新即可。

典型用法

本插件不新增独立 CLI,而是接管 Harness 已有的 web_search 与 web_fetch 工具:在 Agent 或工作流里照常调用这两项能力即可,实际请求会路由到你设置页所选的后端。

典型流程:

  1. 用上述命令把插件装进 web profile。
  2. 在设置页为 Tavily / Exa / Firecrawl 配置密钥(或依赖环境变量)。
  3. 将 web_search 指向搜索后端(如 Tavily),web_fetch 指向抓取后端(如 Firecrawl);需要纯厂商链路时可关闭 YAML 或状态中的 fallbackToHttp。
  4. 在 Harness 对话或自动化中触发联网搜索与页面抓取;多关键词搜索会对应多次厂商调用并合并结果。

错误码包括 WEB_PROVIDER_UNAUTHORIZED、WEB_PROVIDER_QUOTA_EXCEEDED、WEB_PROVIDER_CREDENTIAL_MISSING、WEB_INVALID_URL、WEB_BLOCKED_URL 等,便于在上层做重试或提示(完整列表见 README)。

适用场景与注意

适合:希望在 DSH 里用同一套 web_search / web_fetch 契约,按任务或成本在 Tavily、Exa、Firecrawl 之间切换;或搜索与抓取想拆到不同厂商的用户。

注意:

  • 插件依赖 Node ^22.19.0 || >=24.0.0(见 package.json)。
  • 社区目录 SkillHub 与 DeepSeek / 幻方无官方从属关系;DSH 生态遵循「一切皆插件」,选用前请核对版本与自身合规要求。
  • 本地抓取降级安全模型弱于专用 HTTP 抓取插件;高安全场景请评估 fallbackToHttp 与密钥存放方式。

结尾

dsh-web-tool-provider 把 Tavily、Exa、Firecrawl 收成可互换的 ctx.web 后端,设置页分离搜索与抓取引擎,密钥与额度一目了然,并在抓取侧提供可配置的本地降级。进一步了解实现细节与 YAML 字段,见 GitHub README:https://github.com/nhhc-lxr/dsh-web-tool-provider;插件索引:https://www.skillhub.cn/plugins/nhhc-lxr/dsh-web-tool-provider。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜