DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

mimoxh /

mimoxh/dsh-tavily

Verified

Tavily search and extract providers for DSH (DeepSeek Harness): runs the built-in web_search and web_fetch through Tavily. Zero dependencies, no build step.

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

dsh-tavily

让 DSH 内置的 web_search 和 web_fetch 改走 Tavily,替代随附的 DeepSeek 搜索通道与本地 HTTP 抓取通道。

  • 原生设置页:DSH 设置弹窗新增 Settings → Tavily 一节,直接编辑搜索/抓取参数与 API Key;保存后立即生效,密钥保存在 DSH 凭据库。
  • 不改工具契约:接的是 DSH 的 web 能力 seam(ctx.web),模型侧仍然是原来的 web_search / web_fetch,参数、结果卡片、引用格式全部不变。
  • 两个能力可分开启用:只想换搜索、保留本地抓取时,把 fetchProvider 改回 http 即可(见 6)。
  • 可审计:package.json 声明 dsh.seams: ["web"],离线自测锁定它与 inject 一致。
  • 离线自测:npm test 不需要网络、不需要安装依赖、不需要装 DSH;npm run test:schema 在 npm install 后校验设置 schema。
  • 零构建:浏览器半边是手写脚本,没有打包步骤。

免责声明:这是个人/本地插件,与 DeepSeek 官方、Tavily 官方均无关。 DSH 目前是 developer preview,本插件针对 0.2.1-rc.3 的 seam API 编写; 它依赖的 ctx.web.registerSearchProvider / registerFetchProvider、设置槽位与客户端 primitives 可能随 DSH 版本变化。

兼容性

项 要求
DSH 已在 0.2.1-rc.3 上核对接口(peerDependencies 声明为 ^0.2.0-rc.2)
Node >= 20.3.0 —— 用到 AbortSignal.any()
运行依赖 @deepseek-ai/schemastery ~3.18.5(设置页/schema 用;缺失时插件仍可搜索,但设置页不出现)
安装 本地 link: 安装需在插件目录执行 npm install;发布包由包管理器自动安装依赖
构建步骤 无(client.js 手写)

目录

  • 1. 原理
  • 2. 准备 API key
  • 3. 配置项
  • 4. 安装
  • 5. 结果映射
  • 6. web_fetch 的取舍
  • 7. 验证
  • 8. 排错
  • 9. 已知限制
  • 10. 开发与测试

1. 原理

DSH 的 web 访问是一个可插拔的 seam(@deepseek-ai/dsh-web,即 ctx.web):

组件 角色
@deepseek-ai/dsh-tool-web 面向模型的 web_search / web_fetch 工具
@deepseek-ai/dsh-web seam 本身:注册搜索/抓取提供方,并按 id 选择提供方
@deepseek-ai/dsh-web-search-deepseek 随附的搜索提供方(id:deepseek-official)
@deepseek-ai/dsh-web-fetch-http 随附的抓取提供方(id:http)

DSH 没有内置 Tavily 提供方,所以接入只需要两件事:

  1. 挂载一个注册 tavily 搜索/抓取提供方的插件(本包);
  2. 把 web 行的 searchProvider / fetchProvider 改成 tavily。

这两件事都在本包的 cordis.patch.yml 里完成(组合包 patch 层在 dsh-base / dsh-web-app 之后应用,同一行最后写入者生效,因此可以覆盖默认值)。

⚠️ 必须显式固定 provider id:deepseek-official 只要存在 key 解析器就报告「可用」, 如果两个提供方同时可用且没配置 id,web_search 会以 WEB_PROVIDER_AMBIGUOUS 失败。 本包的 patch 已经替你固定好了。

2. 准备 API key

  1. 在 Tavily 控制台 注册,拿到 tvly- 开头的 key;
  2. 注意额度:一次 web_search 消耗 1 次搜索额度(includeAnswer 会额外消耗), 一次 web_fetch 消耗 1 次 extract 额度(extractDepth: advanced 更多)。

key 有三种放法,推荐设置页或环境变量,避免把密钥写进文件:

方式 存储位置 说明
Settings → Tavily(推荐) DSH 凭据库(~/.dsh/.credentials.yaml) 页面写入 TAVILY_API_KEY;可显示已配置/只读状态;不写进 profile patch
环境变量 启动 DSH 的进程环境 与凭据库同名引用;页面会显示为只读
字面 apiKey cordis.patch.yml 优先级最高,适合临时/overlay;会明文落盘

优先级:字面 apiKey > 凭据库 > 环境变量。

# 当前 shell(临时)
$env:TAVILY_API_KEY = 'tvly-...'
# 用户级(需要完全重启 DSH 才继承到)
[Environment]::SetEnvironmentVariable('TAVILY_API_KEY', 'tvly-...', 'User')

凭据库的引用名由 apiKeyEnv 控制,默认 TAVILY_API_KEY;一般不需要改。页面检测到 patch 里的字面 apiKey 时会禁用密钥输入并提示优先级,避免“保存了 key 却不生效”。

3. 配置项

配置在 cordis.patch.yml 中 web-tavily 行的 config 里;标 是 的字段也可以在 Settings → Tavily 页面里编辑(保存后立即生效,不需要重启)。

字段 默认 设置页 说明
apiKey 无 否 字面 key(tvly- 开头),优先级最高;页面检测到它会禁用凭据输入
apiKeyEnv TAVILY_API_KEY 否(高级) 凭据库引用名;页面按它读写密钥
baseURL https://api.tavily.com 是 Tavily 地址;可指向网关/代理,末尾不要斜杠
searchPath /search 否 搜索端点路径,仅当网关改写了路径才改
extractPath /extract 否 抓取端点路径,同上
timeoutMs 15000 是 单次搜索超时
fetchTimeoutMs 30000 是 单次抓取超时
maxResults 8 是 本提供方上限(≤ 20);调用方只能往下压,不能往上抬
searchDepth basic 是 basic / advanced / fast / ultra-fast
topic general 是 general / news / finance
timeRange 不发送 是 day / week / month / year
days 不发送 是 仅 topic: news 有意义,最近 N 天
country 不发送 是 两位国家代码,例如 us / cn
includeAnswer false 是 false / true / basic / advanced;开启后模型会直接拿到一段答案(消耗额外额度)
includeDomains [] 是 只搜这些域名;页面用逗号/空格分隔,patch 里可写数组
excludeDomains [] 是 排除这些域名;同上
extractDepth basic 是 basic / advanced
extractFormat markdown 是 markdown / text
maxBodyChars 100000 是 抓取正文字符上限,超出截断并标记 truncated
userAgent dsh-tavily/<包版本> 否 请求 UA,默认值跟随 package.json 的 version
headers {} 否 额外请求头(网关鉴权用);同名时覆盖默认的 authorization

页面保存的 volatile 字段写入当前 profile 的 cordis.patch.yml,Host 的下一次请求就会读到,不需要重启。直接改 patch 文件里的非 volatile 字段(searchPath / extractPath / userAgent / headers)仍需让组合包重新加载:桌面端完全重启 DSH;dsh web / dsh tui / dsh headless 下次启动生效。

配置 schema 与设置页

Host 半边现在声明 Config(@deepseek-ai/schemastery),换来:

  • 加载时校验:字段类型/枚举/范围写错会在组合时被拒绝,而不是第一次请求才报错;
  • 原生设置页:web-tavily namespace 被 dsh-settings 提供给浏览器半边,Settings → Tavily 里出现表单;
  • volatile 立即生效:页面保存后 apply() 里的 options thunk 下次请求就重读,不需要重启;
  • 密钥不进 patch:页面通过 DSH 凭据库写 TAVILY_API_KEY。

代价与注意事项:

  • 多了一个包依赖 @deepseek-ai/schemastery ~3.18.5(DSH 自身同款版本)。本地 link: 安装需要在插件目录 npm install;发布包由包管理器安装。
  • 缺少该依赖时 index.js 会动态 import 失败并降级:搜索/抓取照常,设置页不出现,控制台给出警告。这样不会因为漏装依赖导致整行加载失败。
  • DSH 升级 schemastery 时 schema 可能被判定不兼容,需要回归 npm run test:schema;DSH 升级客户端 primitives 时设置页可能需要跟着调整。
  • searchPath / extractPath / userAgent / headers 仍是 patch-only(高级字段,页面不渲染)。

4. 安装

本包已通过 link: 安装进桌面 profile;下面是通用的安装方式。

方式 A:插件管理器 + 本地路径(桌面端)

  1. 在插件目录执行 npm install(安装设置页/schema 所需的 @deepseek-ai/schemastery);
  2. 打开 DSH Web 界面 → 侧栏 插件 → 添加插件;
  3. 粘贴本仓库所在目录的绝对路径,例如 D:\path\to\dsh-tavily;
  4. 点 安装,等 pnpm 跑完;
  5. 完全重启 DSH(关窗口不算,要确认进程退出)。

方式 B:命令行装到某个 profile

npm install                       # 先装本包自己的依赖
dsh plugin --profile web add "D:/path/to/dsh-tavily"

profile 之间互不相干:装进哪个 profile,就只有那个 surface 生效(桌面端是 desktop,只能由 App 管理器安装)。

方式 C:用 --patch overlay 临时覆盖

$env:TAVILY_API_KEY = 'tvly-...'
dsh web --patch ./examples/dsh-tavily.overlay.yml

overlay 只重述已存在的 row,前提是该 profile 里已装本包。

装完必做

  1. 在插件目录执行 npm install(本地 link: 安装不会自动装 link 目标的依赖);
  2. 配好 TAVILY_API_KEY(或 apiKey,或安装后在 Settings → Tavily 里保存);
  3. 完全退出并重启 DSH。

新装/改动组合包后不重启,运行中的 DSH 仍然在用旧组合——表现就是「插件卡片显示已装,但 web_search 还在走 DeepSeek」。新增 dsh.client 声明也必须完全重启,浏览器半边才会被加载。

回退

把 profile 里 web 行的 searchProvider / fetchProvider 改回 deepseek-official / http(或禁用 web-tavily 行),重启即可。

5. 结果映射

搜索(POST /search):

Tavily DSH
results[].url / title / content sources[].url / title / snippet(按 url 去重,无 url 丢弃)
results[].published_date sources[].publishedAt
answer WebSearchResult.content(模型优先读的一段答案)

抓取(POST /extract):

Tavily DSH
results[].raw_content body { kind: 'text', content }(Tavily 已转成 markdown/text)
failed_results[].error 不抛错,返回 statusCode: 502 的结果,正文写明原因

6. web_fetch 的取舍

用 Tavily 接管抓取有三个实际影响,装之前请确认:

  1. 每次抓取都消耗 Tavily 额度,而且比搜索更容易吃额度(extractDepth: advanced 更贵);
  2. 目标 URL 会发送给 Tavily(第三方),抓取由 Tavily 侧执行;
  3. 抓不到内网/本机地址——Tavily 从自己的基础设施访问,http://192.168.x.x、http://localhost 之类不可用。

如果这三点里任何一条不能接受,就只换搜索:把 cordis.patch.yml 里 web 行的 fetchProvider: tavily 改成 fetchProvider: http,web_fetch 继续走随附的本地 HTTP 提供方(带私网拦截、同源重定向限制等安全策略)。

7. 验证

7.1 离线自测(不依赖 DSH、不需要网络)

npm test                # smoke + 浏览器半边注册检查,不需要 node_modules
npm run test:schema     # 需要先 npm install,校验设置 schema
npm run test:all        # 两者一起跑

test/smoke.mjs 覆盖:注册 id、可用性判断、环境变量/凭据库解析、字面 key 优先、缺 key 错误、URL/路径规范化、请求体构造与上限夹逼、结果映射/去重/截断、真实 HTTP 往返(内置 mock Tavily)、401/429/432 报错、取消、超时、不可达、抓取截断、failed_results 降级为结果、URL 策略、dsh.seams 与 inject 一致、dsh.client 清单、patch 结构、发布文件无 UTF-8 BOM。

test/client.mjs 用假的 window.__ModuleLoader__ + mini React/primitives/store 桩执行 client.js,覆盖:模块 id、浏览器半边 inject、settings.section 注册参数(id/order/locale)、whileServed('web-tavily')、页面 hook/actions、字面 key 检测。

test/schema.mjs 覆盖:schema 可被 Schemastery 重建、secret/credential-ref/volatile 元数据、默认值与 normalizeConfig 一致、非法值被拒、覆盖值通过 ref 读出。

7.2 在 DSH 里验证

  1. 完全重启 DSH,打开 Settings:左侧出现 Tavily;
  2. 页面显示当前生效值;修改 maxResults 等字段并保存,检查 ~/.dsh/profiles/<profile>/cordis.patch.yml 出现/更新 web-tavily 行;
  3. 在页面保存 API Key,检查 ~/.dsh/.credentials.yaml 出现 TAVILY_API_KEY 条目(不要打印值),页面显示「已配置」;
  4. 让模型调用一次 web_search(例如「搜索 deepseek harness」),看来源是否来自 Tavily;
  5. 再调用一次 web_fetch(给一个公网 URL),看是否返回 markdown 正文;
  6. 禁用 web-tavily 行后重启/刷新,Settings → Tavily 应消失;重新启用后恢复。

缺 key 时现在会报 WEB_PROVIDER_CREDENTIAL_MISSING(不再是 WEB_PROVIDER_CONFIGURED_UNAVAILABLE),见 8。

8. 排错

现象 / 错误码 原因与处理
WEB_PROVIDER_CONFIGURED_MISSING 组合包没启用/没装成功,tavily 提供方没注册;确认已重启 DSH
WEB_PROVIDER_CONFIGURED_UNAVAILABLE 已注册但 available() 为 false:baseURL 不合法或超时预算非法。缺 key 现在报 WEB_PROVIDER_CREDENTIAL_MISSING,不再走这个错误
WEB_PROVIDER_CREDENTIAL_MISSING 已注册但没有可用 key:在 Settings → Tavily 保存、或设 TAVILY_API_KEY、或在 patch 里写 apiKey
Settings 里没有 Tavily 一节 ① 没 npm install(缺 schemastery,控制台有警告);② web-tavily 行被禁用;③ 没完全重启(新 dsh.client 需要重启);④ 该 profile 没装本包
页面显示「未配置」但搜索可用 key 来自环境变量或 patch 的字面 apiKey;字面 apiKey 优先级最高,页面检测到后会禁用输入
页面提示字面 apiKey 但实际用环境变量 patch 里有一行空的 apiKey: ''(设置服务把“存在”视为已设置)。删掉这行,或填入非空 key
页面显示只读 当前 profile 的设置为只读,或密钥由环境变量提供(describe 报 writable=false)
页面保存失败 设置文档 revision 冲突或 Host 拒绝;草稿保留,刷新后重试
凭据服务不可用 credentials 服务没挂载:key 字段禁用,改用环境变量或字面 apiKey
WEB_PROVIDER_AMBIGUOUS web 行的 provider id 没被钉住(patch 层顺序被更高层覆盖)。在 profile 的 cordis.patch.yml 里显式写 searchProvider: tavily
Tavily search returned HTTP 401 key 无效或过期:核对设置页 / apiKey / TAVILY_API_KEY
HTTP 429 速率限制:降低请求频率后重试
HTTP 432 / HTTP 433 计划额度 / PAYGO 额度用尽:去 Tavily 控制台加额度或升级
HTTP 400 参数被拒:检查 searchDepth / topic / timeRange / days / 域名列表
timed out after ...ms 提高 timeoutMs / fetchTimeoutMs,确认 DSH 主机到 api.tavily.com 的网络与代理
request to ... failed 端点不可达:检查 baseURL、代理、DNS
web_fetch 返回 502 + could not extract ... Tavily 抓不到该页(404/反爬/PDF 等):换 URL 或用本地 fetchProvider: http
web_fetch 报 WEB_INVALID_URL / WEB_BLOCKED_URL 只接受 http(s) 且 URL 里不能带用户名密码
装了但 web_search 还走 DeepSeek 没完全重启 DSH;或该 profile 里 web 行仍是 deepseek-official
插件卡片显示「已关闭」 运行中的 DSH 是在装插件之前启动的。完全重启

9. 已知限制

  • 未做真实 API 联调:创建这个插件时,本机 DNS 把 api.tavily.com / docs.tavily.com 解析到 198.18.0.0/15(代理 fake-IP 段),DSH 自带的 web_fetch 会以「解析到非公网 IP」拒绝; 插件的 fetch 走 Node 原生实现、通常会经系统代理,但没有真实 key 就没有验证过。 安装后第一次调用请按 7.2 现场确认。
  • 字段与错误码来源:Tavily 请求/响应字段(search_depth、include_answer、raw_content、 failed_results 等)与 401/429/432/433 语义按公开文档与官方 SDK 行为实现;文档站不可达时 无法二次核对。
  • 可用性是乐观的:配置了凭据引用(默认 TAVILY_API_KEY)后 available() 就为 true, 真正的 key 在每次请求时解析;缺 key 时由 WEB_PROVIDER_CREDENTIAL_MISSING 报出,而不是 让 seam 报 WEB_PROVIDER_CONFIGURED_UNAVAILABLE。这是为了支持凭据库/环境变量在运行时变化。
  • 设置页依赖 DSH 客户端 primitives:SettingsFormModel / SettingsForm / SettingsValueField / SettingsSecretField 是 0.2.1-rc.3 的基线模块 API;DSH 升级后 可能需要按新版本调整 client.js(与 dsh-cloud-control 的浏览器半边同类风险)。
  • 设置页对所有启用本 bundle 的 profile 可见:它是 profile 级设置,不做“只有用 Tavily 的人 才显示”的额外门控;不想看到它就把 bundle 从 profile 移除。
  • 字面 apiKey 优先:保留兼容;页面检测到后会禁用凭据输入并提示,避免“保存了 key 却不生效”。
  • Web/桌面 surface 的 web_search / web_fetch 工具来自 agent preset(tool-web); 若某个 preset 没挂 tool-web,seam 里注册了提供方也没有工具去调它。

10. 开发与测试

文件 作用
index.js 两个 provider 的实现:apply / inject、配置规整、凭据解析、请求体构造、结果映射、错误码;可选 schema 的动态加载
lib/defaults.js 默认值、枚举、凭据引用名;host 与 schema 共用,避免漂移
lib/schema.js Config(@deepseek-ai/schemastery),驱动设置页与加载时校验
client.js 浏览器半边:settings.section 注册、表单、凭据状态、清除密钥
cordis.patch.yml 组合包 patch:固定 web 的两个 provider id + 挂载 web-tavily 行
package.json 组合包清单(dsh.bundle.patch、dsh.client、dsh.seams、依赖、展示元信息、icon 导出)
locale/zh.json、locale/en.json 插件管理器卡片标题与描述
icon.svg 插件图标(原创)
examples/dsh-tavily.overlay.yml dsh --patch 用的 overlay
test/smoke.mjs 离线 provider 自测(内置 mock Tavily)
test/client.mjs 离线浏览器半边注册检查(mini React/primitives/store 桩)
test/schema.mjs 设置 schema 校验(需要 npm install)
npm install          # 设置页/schema 依赖(cosmokit、standard-schema 会一起装)
npm test             # 离线:smoke + client,不需要 node_modules
npm run test:schema  # 需要上面的 npm install
npm run test:all     # 两者一起

npm test 不依赖 node_modules:index.js 对 schema 用动态 import,缺依赖时降级为“无设置页”,测试里用 DSH_TAVILY_QUIET=1 静音该警告。

修改 lib/defaults.js 里的 PACKAGE_VERSION 时记得同步 package.json 的 version—— test/smoke.mjs 会检查默认 User-Agent 与包版本是否一致。修改 schema 时同时跑 npm run test:schema。

License

MIT

—/ 5

No ratings yet

Verified DSH bundle

Commit 3881ab4ebd70

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