dsh-tavily-search
Verified@zhiqiangme/dsh-tavily-search · v26.10.13 · MIT · Web UI
用 Tavily 给 DSH 的网页搜索供数:在 DSH 进程内提供 127.0.0.1:8787/v1 搜索接口,API Key 存在 DSH 凭据库。
Install
dsh plugin add @zhiqiangme/dsh-tavily-search Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Tags
Creators
Readme
@zhiqiangme/dsh-tavily-search
DeepSeek Harness(DSH)插件:用 Tavily 给 DSH 的「网页搜索」供数。
DSH 自带的搜索提供方(@deepseek-ai/dsh-web-search-deepseek)向「接口地址」发 Anthropic Messages 请求,
只解析响应里的 web_search_tool_result 结构化块。本插件在 DSH 进程内监听 127.0.0.1:8787,
把这类请求转成一次 Tavily 检索,再合成提供方能解析的响应——不调用任何模型。
DSH 网页搜索 ── POST http://127.0.0.1:8787/v1/messages ──▶ 本插件(DSH 进程内) ── POST /search ──▶ Tavily
◀── server_tool_use + web_search_tool_result + 引用摘要 ──
把 DSH「插件 → 网页搜索」的接口地址设为 http://127.0.0.1:8787/v1 即接入(插件页卡片里有一键按钮)。
插件页卡片
在 DSH「插件 → Tavily 联网搜索」里有一张配置卡片,分四块:
| 区块 | 做什么 | 走哪条通道 |
|---|---|---|
| API Key | 可添加多个 Tavily API Key(最多 10 个),逐个列出、各自单独删除(删除前二次确认);列表只显示末 4 位用于辨认,从不回显完整值 | 写入 / 删除走 DSH 凭据库(remote.credentials),与内置「网页搜索」页同一条路;列表走宿主半侧路由 /plugins/dsh-tavily-search/keys |
| 搜索接口 | 显示 127.0.0.1:8787/v1 的状态(运行中 / 外部实例 / 端口被占用 / 启动失败);「测试搜索」按 DSH 的请求形状真打一次 |
宿主半侧路由 /plugins/dsh-tavily-search/status、/test |
| 网页搜索接入 | 显示「网页搜索」当前的接口地址;未接入时一键改成本插件的端点,已接入时可恢复默认 | configForms.get('web-search-deepseek'),即内置网页搜索页编辑的同一个设置命名空间 |
| 插件更新 | 显示当前运行版本与 npm 最新版本;装了 dshmarket 时一键更新并显示进度,没装时只提示有新版本 | 版本检查走宿主半侧路由 /plugins/dsh-tavily-search/version(同时问 npm 官方源与 npmmirror,取较高者,缓存 10 分钟);更新走 dshmarket 的公开更新 API v1 |
几点说明:
- 卡片只改网页搜索的接口地址,不动它的
apiKeyEnv:恢复默认后网页搜索会把那个 key 发给 DeepSeek 官方接口, 所以不能让它指向 Tavily 的 key。 - DSH 的网页搜索只在它自己那栏 API Key 非空时才发起搜索(DeepSeek 账号模型除外)。本插件不校验那个值, 为空时卡片会提示"填任意非空字符串即可"。
- 密钥输入框用宿主的
SettingsSecretField(与内置网页搜索页同款);宿主组件拿不到时退回自带的同款输入框。 - 一键更新不自己跑 pnpm:DSH 自带的插件管理器不支持升级已安装的插件,本插件把更新交给 dshmarket, 由它处理 profile 锁、文件占用、回滚与版本核对。桌面版更新完成后要重启 DSH 才会换上新代码 (桌面版的重启归桌面壳管,卡片不提供重启按钮)。新版本刚发布时可能被 pnpm 的发布冷却期挡下,卡片会给出「强制更新」。
- 一键更新只对从 npm 安装的情况有效。从本地目录(
file:)装时 dshmarket 拒绝更新(locally linked plugins update from their checkout), 卡片会先向 dshmarket 查询安装来源,这种情况下不显示更新按钮,改为提示:拉取新代码后重新安装,或改为从 npm 安装。
行为
- 进程内监听:随插件加载监听、随插件卸载关闭,没有外部进程;出站请求走 DSH 的代理策略。
- 搜索接口只供宿主 / CLI 调用:带
Origin或跨站 Fetch 标记的浏览器请求返回 403,避免网页借本机接口消耗 Tavily 额度。 插件卡片的「测试搜索」通过宿主面板路由转发,照常可用。 - 不抢端口:端口上已有同类适配服务(例如用下文"独立运行"起的实例)时只记日志,DSH 的请求由它处理; 端口被别的程序占着时记错误日志。插件重载时会先等约 2s,让上一个实例释放端口。
- 失败不阻断:监听不上只写日志,DSH 本身照常可用。
- API Key 存在 DSH 凭据库:引用名默认
TAVILY_API_KEY,值在~/.dsh/.credentials.yaml,不写进任何设置文件。 每次请求现取,改 key 不用重启;缺 key 时搜索返回明确的错误,提示去哪里填写。 - 多个 key:第 1 个是
TAVILY_API_KEY,其余依次是TAVILY_API_KEY_2…TAVILY_API_KEY_10。请求间轮流使用, 均摊各 key 的额度;某个 key 被 Tavily 拒绝(401 / 403 / 429 / 432 / 433:无效、禁用、限流、额度用尽)时当场换下一个重试。 5xx、网络错误、超时与 key 无关,不换 key 重试。 - 只依赖 Node 内置模块:不声明 Host Service 依赖;凭据服务缺席时退回同名环境变量。
安装到 profile
从 npm 安装:先完全退出 DSH 桌面版,然后在终端运行(dsh 命令随 DSH 桌面版一起安装),重新打开 DSH 生效:
dsh plugin --profile desktop add @zhiqiangme/dsh-tavily-search
# 更新:dsh plugin --profile desktop update --latest @zhiqiangme/dsh-tavily-search
装到 Web / CLI 就把 desktop 换成 web / headless。更新要带 --latest:版本号按日期编排(26.10.11),
跨年时主版本号会变。更多说明见仓库 README。
从源码安装:克隆仓库后双击根目录的 install-plugins.cmd,
按提示选择插件和 profile(说明见仓库 README),完成后重启 DSH 生效。
改了本目录的代码后再运行一次同样的"安装 / 更新"即可换上新代码。
手动安装等价于(先完全退出桌面版):
dsh plugin --profile desktop add "file:<仓库路径>\dsh-tavily-search"
file:依赖是拷贝进 profile 的node_modules,改了代码后再add(包括--force)pnpm 都认为"已是最新", 要先dsh plugin --profile desktop remove @zhiqiangme/dsh-tavily-search再add。安装脚本会比对文件哈希自动做这一步。
配置
在 profile 的 cordis.patch.yml 里按行 id 覆盖(全部可省略):
- id: dsh-tavily-search
name: '@zhiqiangme/dsh-tavily-search' # 包名以 @ 开头,YAML 里必须加引号
config:
port: 8787
maxResults: 8
searchDepth: basic
| 字段 | 默认 | 说明 |
|---|---|---|
enabled |
true |
只有显式 false 才不监听 |
host / port |
127.0.0.1 / 8787 |
监听地址;改了端口要同步改网页搜索的接口地址 |
apiKeyRef |
TAVILY_API_KEY |
第 1 个 key 的凭据引用名(环境变量名形状);其余 key 为 <apiKeyRef>_2 … _10 |
importEnvFile |
空 | 一次性导入:凭据库里还没有 key 时,从这个 .env 里取同名变量写进凭据库 |
tavilyBaseUrl |
https://api.tavily.com |
Tavily 端点,测试时可指向 mock |
maxResults |
8 |
单次检索返回条数 |
searchDepth |
空 | basic / advanced,留空用 Tavily 默认档 |
timeoutMs |
30000 |
单次 Tavily 调用超时,超时按 502 返回 |
maxQueryChars |
600 |
检索词长度上限,超出 400 |
shimApiKey |
空 | 非空时校验调用方的 x-api-key / Bearer |
任何非法值都会退回默认值,不会让插件加载失败。
独立运行
不开 DSH 也能起一个同样的接口(排障、给别的客户端用)。没有凭据库,配置从环境变量读
(TAVILY_API_KEY,多个 key 再加 TAVILY_API_KEY_2 …;LISTEN、TAVILY_MAX_RESULTS、TAVILY_SEARCH_DEPTH……):
$env:TAVILY_API_KEY = 'tvly-…'
node lib/cli.js # 前台监听,Ctrl+C 退出
node lib/cli.js --print-config # 只打印解析出的配置
测试
node --test test/*.test.mjs
注意别写 node --test test/:Node 24 会把目录参数当成模块去 require,直接报 MODULE_NOT_FOUND。
test/helpers.mjs 不带 .test,不会被当成用例执行。