- Accueil
- Plugins
- Modèles et fournisseurs
- dsh-web-search-tavily
dsh-web-search-tavily
zzy-cl/dsh-web-search-tavily
Multi-key Tavily search provider for DeepSeek Harness (ctx.web) with a live settings card in the web plugin configuration page
Installer
dsh plugin --profile web add github:zzy-cl/dsh-web-search-tavilyREADME
dsh-web-search-tavily
0.2.0 命名对齐:
0.1.x的tavily-search已全面对齐官方web-search-*族,更名为web-search-tavily。从0.1.x升级需将$DSH_HOME/settings.yaml中的tavily-search:键手动改为web-search-tavily:(或在设置卡片重新填入),patch会自动清理旧tavily-search残留。
为 DeepSeek Harness(dsh)提供基于 Tavily 的联网搜索能力。
- 多 key 轮询:支持配置 1..n 个 Tavily API key,按轮询调度;某个 key 触发 429(免费额度耗尽/限流)时自动冷却并切换到下一个 key,把多个免费账号的月额度叠加起来。
- 可视化配置:安装后在 设置 → 插件 → 插件配置 出现「Tavily 搜索」卡片,可增删 key、填密钥(只写输入框,永不回传)、调搜索参数,全部热生效无需重启。
- 零侵入:注册到官方
ctx.web能力 seam,模型侧web_search工具 schema 不变,内置 DeepSeek 搜索被替换。
兼容性
| 项 | 值 |
|---|---|
| DeepSeek Harness | 0.1.0-rc.8(next,developer preview,接口可能破坏性变更;rc.6 仍兼容) |
| Node.js | >=20 |
| 安装 | dsh plugin(pnpm profile) |
工作原理
- 插件注册一个
WebSearchProvider(id:tavily)到ctx.web,patch 把searchProvider从deepseek-official改为tavily。内置web-search-deepseek插件保持注册(它的设置卡片继续可用),只是不再被选中。 keys[]组成轮询池:每次搜索按顺序取下一个可用 key;429→ 该 key 冷却(默认 60s)→ 换下一个;全部失败时抛出结构化错误(只含 key 的id,不含密钥)。web-search-tavily设置 namespace 通过installSettingsSection注册,schema 即表单;用户改动经$DSH_HOME/settings.yaml热加载,provider 下次搜索即用新配置。
rc.6 / rc.8 差异:
rc.6的@deepseek-ai/dsh-host-apiproxy对「设置页插件配置卡片」有一份硬编码 allowlist,本插件携带守卫式补丁在首次启动时把web-search-tavily加入该列表;rc.7+已移除该 allowlist,改为动态注册自动暴露,补丁在rc.8上自动成为skipped-version无操作(日志为allowlist was removed… patch not needed)。详见 allowlist 补丁。
安装
方式 A:本地目录(开发/自用,推荐)
先构建产物:
npm install
npm run build
然后安装进 web profile:
dsh plugin --profile web add ./dsh-web-search-tavily
本地目录安装走 pnpm link,不需要 allowBuilds 授权。
方式 B:发布到 npm 后
dsh plugin --profile web add @zzy001/dsh-web-search-tavily
方式 C:GitHub(需要授权构建)
dsh plugin --profile web add "github:zzy-cl/dsh-web-search-tavily#<commit-sha>"
pnpm ≥10 首次安装会拒绝运行 git 依赖的 prepare 构建脚本。按 dsh 打印的提示,把包键 @zzy001/dsh-web-search-tavily 加入该 profile 的 pnpm-workspace.yaml:
allowBuilds:
'@zzy001/dsh-web-search-tavily': true
然后重新执行 add。允许构建 = 允许该包代码在安装时于你机器上执行,仅对可信源码使用;更稳妥的做法是用方式 B(npm 分发预构建产物)或方式 D(tarball,无需授权)。
方式 D:tarball(无构建授权)
npm pack # 或 pnpm pack
dsh plugin --profile web add ./zzy001-dsh-web-search-tavily-0.3.0.tgz
所有
dsh plugin add方式都需要本机有 pnpm(dsh CLI 不内置 pnpm,profile 由 pnpm 管理):npm install -g pnpm或corepack enable pnpm。
使用 npx @deepseek-ai/dsh 启动的用户
如果 dsh 是通过 npx @deepseek-ai/dsh web 运行的(插件装在 profile,内置包从 npx 缓存解析),安装流程:
npm install -g pnpm
npx @deepseek-ai/dsh plugin --profile web add "D:\...\dsh-web-search-tavily" # 本地目录,或 npm 包名/tarball/github:
npx @deepseek-ai/dsh web # 第 1 次启动:自动对 dsh 安装目录(npx 缓存)应用 allowlist 补丁
npx @deepseek-ai/dsh web # 第 2 次启动:设置页卡片出现
allowlist 补丁会定位dsh 进程实际加载的 @deepseek-ai/dsh-host-apiproxy 副本(解析链:进程入口 → 插件目录 → $DSH_HOME/profiles/* → npx 缓存),不会误打仓库里的 devDependency 副本。若卡片未出现,用 dsh-web-search-tavily status 确认 packageRoot 指向 dsh 安装目录。
免 pnpm 快速试跑(仅验证搜索,无设置卡片):仓库根有 dev.cordis.yml,用它做 --patch overlay:
$env:TAVILY_API_KEY = "tvly-你的key"
npx @deepseek-ai/dsh web --patch "D:\项目合集\dsh-plugins\dsh-web-search-tavily\dev.cordis.yml"
安装后
-
重启一次
dsh(allowlist 补丁在启动时应用,卡片下次启动才被服务)。 -
验证补丁与配置层:
dsh --profile web --dump-config # 应看到 web-search-tavily 行、web.searchProvider: tavily、web-search-deepseek 行仍启用 pnpm --dir "$DSH_HOME/profiles/web" exec dsh-web-search-tavily status -
打开 Web UI
http://127.0.0.1:3080→ 设置 → 模型:填入 DeepSeek API key(聊天仍走 DeepSeek,只有搜索走 Tavily)。
发布
官方没有独立的插件市场;分发方式就是 npm 注册表(bundle 本质是带 dsh.bundle 清单的 npm 包)与 GitHub,发现性靠 GitHub 仓库的 dsh-plugin topic。
发布到 npm(推荐)
npm login
npm publish # 自动跑 prepare → tsdown → 发布预构建 lib + cordis.patch.yml + bin
发布前用 npm pack --dry-run 复核产物。发布后用户安装即方式 B,无需 allowBuilds(装的是预构建代码)。
发布到 GitHub
git remote add origin git@github.com:zzy-cl/dsh-web-search-tavily.git
git push -u origin master
给仓库打 topics(GitHub 仓库页 Settings → Topics):dsh-plugin、deepseek-harness、tavily、web-search。用户通过 github:zzy-cl/dsh-web-search-tavily#<commit-sha> 安装(方式 C,需要 allowBuilds 授权,因为 git 安装会跑 prepare 构建)。
配置
环境变量(开箱即用)
bundle 默认带一个 main key 引用 TAVILY_API_KEY 环境变量:
# Windows PowerShell
$env:TAVILY_API_KEY = "tvly-你的key"
# POSIX
export TAVILY_API_KEY="tvly-你的key"
设置页卡片(推荐,支持多 key)
安装并重启后:设置 → 插件 → 插件配置 → Tavily 搜索。
- API Keys(轮询池):添加/移除 key 行,每行填
id(统计/报错里的名字)+ 可选的apiKeyEnv(环境变量名,不是密钥)+ 只写密钥输入框(留空保持当前密钥,提交后不再回传)。密钥存入顶层apiKeys{}字典,部分保存深度合并,改一个 key 不影响其他 key。 - 卡片中可改:搜索深度
basic|advanced、topic、time_range、include_domains/exclude_domains、include_answer、maxResults(1–20)、429 冷却cooldownMs、baseURL。 - 改动写入
$DSH_HOME/settings.yaml,热生效,无需重启;密钥按 key 显示"已配置/未配置"徽标(值永不回传)。 - 卡片对
apiKeyEnv做实时校验:把tvly-…密钥字面量填进该栏会标红并阻止保存(见 Troubleshooting 第一条)。
基础配置中的 key(如
main→$TAVILY_API_KEY)会始终参与轮询;若在卡片里给同一id填新密钥则覆盖环境变量。密钥与 env 引用的优先级:apiKeys{}内联 >apiKeyEnv环境变量。
搜索参数说明
| 设置项 | Tavily 参数 | 说明 |
|---|---|---|
keys[] | — | 轮询池名单(id + 可选 apiKeyEnv);密钥在 apiKeys{} 字典里 |
apiKeys{} | — | id → 密钥 的顶层字典(secret 脱敏,UI 只写) |
baseURL | — | 默认 https://api.tavily.com |
searchDepth | search_depth | basic(1 积分)/ advanced(2 积分) |
topic | topic | general/news/finance/... |
timeRange | time_range | day/week/month/year |
includeDomains | include_domains | 仅这些域名 |
excludeDomains | exclude_domains | 排除这些域名 |
includeAnswer | include_answer | 生成的回答映射为模型可见 content |
maxResults | max_results | 请求未带 maxResults 时的默认条数 |
cooldownMs | — | 429 后该 key 冷却毫秒数(默认 60000) |
使用验证
在 Web UI 发起需要联网的问题(例如「搜索今天的人工智能新闻」),确认:
web_search工具调用返回 Tavily 结果(含answer与 citations);- dsh 进程终端出现轮询/切换日志(形如
[web-search-tavily] ... key 'main' ...); - 多个 key 时把某个 key 手动填错或耗尽,观察到自动切换。
Troubleshooting
1. 「provider unavailable」/ 搜索报 WEB_PROVIDER_CREDENTIAL_MISSING 或无可用 key
最常见原因:把 Tavily 密钥字面量(tvly-…)填进了 apiKeyEnv 字段。
# ❌ 错误:apiKeyEnv 是环境变量名,不是密钥
web-search-tavily:
keys:
- id: main
apiKeyEnv: tvly-dev-xxxxx
# ✅ 正确 A:密钥放顶层 apiKeys{} 字典
web-search-tavily:
apiKeys:
main: tvly-dev-xxxxx
# ✅ 正确 B:apiKeyEnv 指向真实存在的环境变量
# 且启动 dsh 前设置 $env:TAVILY_API_KEY = "tvly-dev-xxxxx"
web-search-tavily:
keys:
- id: main
apiKeyEnv: TAVILY_API_KEY
插件自 0.1.0 起对此做了三重防护:设置卡片实时标红并阻止保存;启动时在 dsh 日志输出配置诊断([web-search-tavily] 配置诊断: key 'main': apiKeyEnv 填入了疑似密钥字面量…);搜索报错消息直接指向 web-search-tavily settings 排查。
2. 日志出现「key 解析结果: N 个警告」
说明有 key 未解析到凭证(env 不存在 / apiKeys 未配置 / 被过滤)。按警告文案逐条修复;警告会在配置修正后自动消失(无需重启)。
3. 所有 key 报 429 后仍失败
免费额度耗尽或限流,属预期行为:默认冷却 60s 后自动重试,可调 cooldownMs,或往轮询池加 key。
4. 设置卡片不出现
先 dsh-web-search-tavily status 确认 allowlist 补丁状态(见 allowlist 补丁);首次安装需重启 dsh 两次。
allowlist 补丁
它做什么:把 web-search-tavily 追加进已安装的 @deepseek-ai/dsh-host-apiproxy/lib 中 WEB_SETTINGS_NAMESPACES 数组,使设置页服务该 namespace。只插入 , "web-search-tavily" 一个片段,幂等。
守卫:
- 仅当安装版本为
0.1.0-rc.6时执行;rc.7+上自动skipped-version(allowlist was removed in rc.7+),仅打印info,不告警不破坏任何东西。 - 幂等:重复 apply 返回
already-applied;restore 只移除自己插入的片段。 - 写入采用临时文件 + rename;
discoverJsFiles防符号链接环。
命令(在 profile 目录下):
pnpm --dir "$DSH_HOME/profiles/web" exec dsh-web-search-tavily status # patched/clean/...
pnpm --dir "$DSH_HOME/profiles/web" exec dsh-web-search-tavily apply # 手动应用
pnpm --dir "$DSH_HOME/profiles/web" exec dsh-web-search-tavily restore # 卸载前还原
Windows:
$DSH_HOME默认在%USERPROFILE%\.dsh,把$DSH_HOME/profiles/web换成实际绝对路径。
升级 / 卸载
- dsh 升级后:先
dsh-web-search-tavily status确认补丁状态;rc.8已改为动态注册,status应为skipped-version且提示patch not needed,属正常。 - 卸载:先
restore再dsh plugin --profile web remove @zzy001/dsh-web-search-tavily。卸载后web行恢复默认searchProvider: deepseek-official。
安全与合规
- 密钥经
role('secret')处理:只写输入、永不回传;存储于本地settings.yaml。 - Tavily 收到搜索词与启用的搜索参数;
include_answer会把第三方页面内容带入模型上下文,按需关闭。 - 多账号叠加免费额度可能违反 Tavily 服务条款,请自行评估风险。
开发
npm install
npm run check # tsc --noEmit
npm test # vitest
npm run build # tsdown → lib/
npm pack --dry-run
结构:
src/
├── index.ts # 插件入口(name/inject/apply + 启动时补丁)
├── settings.ts # web-search-tavily 设置 namespace + schema + resolveProviderOptions
├── shared.ts # 共享校验(ENV 变量名 / 密钥字面量判定,消除双维护)
├── provider.ts # TavilySearchProvider:轮询 + 429 冷却 + 映射
├── rotation.ts # 轮询/冷却状态机(纯逻辑,可测)
├── patch.ts # apiproxy allowlist 守卫式补丁(rc.6 专用,rc.7+ 自失效)
└── types.ts # Tavily API 类型
client/client.js # 设置卡片(ModuleLoader bundle,含 hash 失效回退样式)
bin/ # dsh-web-search-tavily CLI(status/apply/restore)
License
MIT。
Plugins associés
dsh-plugin-subscriptions
v1ki/dsh-plugin-subscriptions
dsh-commandcode-provider
mars-sea/dsh-commandcode-provider
dockyard-dsh
aitabby/dockyard-dsh
dsh-codex-connect
franksong2702/dsh-codex-connect