Vai al contenuto principale
Z

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

Installazione

dsh plugin --profile web add github:zzy-cl/dsh-web-search-tavily

README

dsh-web-search-tavily

0.2.0 命名对齐0.1.xtavily-search 已全面对齐官方 web-search-* 族,更名为 web-search-tavily。从 0.1.x 升级需将 $DSH_HOME/settings.yaml 中的 tavily-search: 键手动改为 web-search-tavily:(或在设置卡片重新填入),patch 会自动清理旧 tavily-search 残留。

DeepSeek Harnessdsh)提供基于 Tavily 的联网搜索能力。

  • 多 key 轮询:支持配置 1..n 个 Tavily API key,按轮询调度;某个 key 触发 429(免费额度耗尽/限流)时自动冷却并切换到下一个 key,把多个免费账号的月额度叠加起来。
  • 可视化配置:安装后在 设置 → 插件 → 插件配置 出现「Tavily 搜索」卡片,可增删 key、填密钥(只写输入框,永不回传)、调搜索参数,全部热生效无需重启
  • 零侵入:注册到官方 ctx.web 能力 seam,模型侧 web_search 工具 schema 不变,内置 DeepSeek 搜索被替换。

兼容性

DeepSeek Harness0.1.0-rc.8next,developer preview,接口可能破坏性变更;rc.6 仍兼容)
Node.js>=20
安装dsh plugin(pnpm profile)

工作原理

  1. 插件注册一个 WebSearchProvider(id: tavily)到 ctx.web,patch 把 searchProviderdeepseek-official 改为 tavily。内置 web-search-deepseek 插件保持注册(它的设置卡片继续可用),只是不再被选中。
  2. keys[] 组成轮询池:每次搜索按顺序取下一个可用 key;429 → 该 key 冷却(默认 60s)→ 换下一个;全部失败时抛出结构化错误(只含 key 的 id,不含密钥)。
  3. 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 pnpmcorepack 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"

安装后

  1. 重启一次 dsh(allowlist 补丁在启动时应用,卡片下次启动才被服务)。

  2. 验证补丁与配置层:

    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
    
  3. 打开 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-plugindeepseek-harnesstavilyweb-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|advancedtopictime_rangeinclude_domains/exclude_domainsinclude_answermaxResults(1–20)、429 冷却 cooldownMsbaseURL
  • 改动写入 $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
searchDepthsearch_depthbasic(1 积分)/ advanced(2 积分)
topictopicgeneral/news/finance/...
timeRangetime_rangeday/week/month/year
includeDomainsinclude_domains仅这些域名
excludeDomainsexclude_domains排除这些域名
includeAnswerinclude_answer生成的回答映射为模型可见 content
maxResultsmax_results请求未带 maxResults 时的默认条数
cooldownMs429 后该 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/libWEB_SETTINGS_NAMESPACES 数组,使设置页服务该 namespace。只插入 , "web-search-tavily" 一个片段,幂等。

守卫

  • 仅当安装版本为 0.1.0-rc.6 时执行;rc.7+ 上自动 skipped-versionallowlist 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,属正常。
  • 卸载:先 restoredsh 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。

Plugin correlati