npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-tavily-web-search

v0.8.0

Published

Tavily-backed WebSearchProvider with a pool-only multi-key settings UI, round-robin search, and official per-key usage inspection.

Readme

dsh-tavily-web-search

Tavily 支持的 WebSearchProvider,用于 DeepSeek Harness 的 web 能力缝(ctx.web)。

它把模型侧 web_search 工具的后端从 DeepSeek 官方搜索 换成 Tavily —— 每次搜索直接调用 POST https://api.tavily.com/search,不再走 DeepSeek API(不再消耗 DeepSeek 的模型 token/配额)。其他一切不变:web_search / web_fetch 工具照旧,LLM、会话等不受影响。

当前版本适配 DSH 0.2.0-rc.1(@deepseek-ai/dsh-* 0.2.0-rc.1 / @deepseek-ai/cordis 4.0.4)。

从 0.7.0 升级到 0.8.0 只改了「兼容声明」:DSH 0.2.0 启动前会校验每个 profile 插件的 peerDependencies 是否满足当前运行时(见下方「与 DSH 0.2.0 的兼容」)。插件用到的所有 API 在 0.1.7 → 0.2.0 之间没有变化,因此 host/client 两半的实现保持原样。

特性

  • 多 Key 池:在 Web 设置页添加、重命名、替换、启停和删除多个 Tavily API Key。
  • 轮询搜索:搜索在「启用且已配置」的 Key 之间轮询(round-robin);被停用的 Key 不参与搜索。
  • 用量查询:每个 Key 均可点击「查询用量」,调用 Tavily 官方 GET /usage 读取实时积分用量,界面显示 已用 / 总量 和进度条(如 79 / 1000 积分)。
    • 停用的 Key 仍可查询用量,只是不参与搜索。
  • 凭据安全:Key 值通过凭据服务(ctx.credentials)存储,永不写入配置文件,也不会返回浏览器;配置里只保存 Key 的显示名称、生成的凭据引用和启用状态。
  • 超时保护:timeoutMs 会与调用方的取消信号合并,超时报中文错误。
  • 中文报错/提示:插件产生的错误与提示均为中文,便于排查。

工作原理

  • 插件导出一个 Config schema 和一个 apply,注册 id 为 tavily 的 WebSearchProvider(通过 ctx.web.registerSearchProvider)。
  • bundle patch 把 web 服务的 searchProvider 从 deepseek-official 改为 tavily,并插入本插件的行 web-search-tavily。
  • 每次 web_search 调用 → 直接向 Tavily REST API 发请求 → 结果映射为 DSH 标准 WebSearchResult(url / title / snippet / publishedAt)。
  • 模型侧的 web_search 工具本身(@deepseek-ai/dsh-tool-web)完全不动,所以模型看到的能力没有任何变化。

DSH 0.1.7 起沿用至今的配置模型

自 0.1.7 起(0.2.0 未变)取消了「插件注册设置命名空间」的旧模型(ctx.settings.installSection / ctx.settingsScope):

  • 插件自己的 Config 就是配置界面。配置服务的 describe() 按 profile 行 id 暴露每个插件条目的 schema 与实时取值,浏览器端用 ctx.configForms.get('<行 id>') 拿到共享表单。
  • 因此行 id = 设置命名空间:本插件的行 id 是 web-search-tavily,客户端 TAVILY_NS 与之一致。
  • 只有声明为 .volatile() 的字段才会被渲染为可编辑项,并且每次操作都读取实时值(无需重启、无需重挂插件)。
  • 保存走 mutate(ops, revision) 的路径写入 + 版本栅栏,一次保存是一次原子写入。
  • 本插件自己提供设置页面,所以 apply 里调用 ctx.settings.configure({ auto: false }, ctx.fiber),避免配置服务再自动生成一个重复的页面。

与 DSH 0.2.0 的兼容

DSH 0.2.0 新增了一道启动前置校验:在挂载任何插件之前,launcher 会读取每个 profile 行(以及每个 bundle)的 package.json,把它声明的 @deepseek-ai/dsh / @deepseek-ai/dsh-* peer 依赖与当前运行时版本做 semver 比对;只要有一个区间不满足,该行就被静默禁用(dsh --dump-config 会打印 disabling profile plugin ...)。这正是 0.7.0 在 0.2.0-rc.1 上失效的原因:它的 peer 区间是 ^0.1.7-alpha.1,而 0.2.0-rc.1 不在其中。

因此 0.8.0 的改动集中在 manifest:

| 项 | 0.7.0 | 0.8.0 | |---|---|---| | peerDependencies 的 dsh 区间 | ^0.1.7-alpha.1 | ^0.2.0-rc.1 | | @deepseek-ai/cordis | ^4.0.3 | ^4.0.4 | | @deepseek-ai/schemastery | ^3.18.3 | ^3.18.4 | | engines.dsh | 无 | >=0.2.0-rc.1 <0.3.0 |

engines.dsh 目前只是声明性元数据(0.2.0 的 launcher 不读取 engines),真正决定行是否挂载的是 peerDependencies。两者写同一个区间,是为了让「只读 manifest」和「实际校验」得出同一结论。

插件用到的 host/client API 在 0.1.7 → 0.2.0 之间没有破坏性变化,所以 lib/index.js(host 半,手写维护)与 src/client/ 的实现无需改动。唯一的构建侧调整是 tsdown.config.ts 把已弃用的 external / noExternal 换成现在的 deps.neverBundle / deps.alwaysBundle(产物逐字节等价)。

浏览器半的模块表(platform seed)在 0.2.0 与 0.1.7 相同,仍是 react / react/jsx-runtime / react-dom / react-dom/client / @deepseek-ai/cordis / @deepseek-ai/dsh-client-store / @deepseek-ai/dsh-client-ui-slots / @deepseek-ai/dsh-client-ui-primitives / @deepseek-ai/dsh-client-ui-dockkit。 lib/client.js 只 require 其中的 @deepseek-ai/dsh-client-ui-primitives;其余 dsh 包(renderer、 settings、locale、api-remotes、credentials)都是仅类型导入,编译后被擦除。

验证兼容性

npm run verify   # 5 道闸门,见下
  1. verify-compat.mjs —— 直接调用 DSH 自己的 evaluatePluginCompatibility(dsh-app-boot 导出, 也就是启动校验用的同一个函数),断言本包的 manifest 能通过 0.2.0-rc.1 的前置校验;同时守住 peer 区间不再回退到 0.1.x。
  2. verify-client-manifest.mjs —— 用 dsh-client-modules 真正的 parseDshClient 校验 dsh.client 声明,并检查 lib/client.js 的每个 require 都落在平台种子或声明的 external 里。
  3. verify-bundle.mjs —— 产物的 loader 交接、平台种子、旧 API 残留。
  4. verify-client.mjs —— 浏览器半运行时检查:注意它不再手抄 SettingsFormModel,而是从 @deepseek-ai/dsh-client-ui-primitives 的真实产物里就地提取该实现来跑,避免转录副本与线上实现漂移。
  5. smoke.mjs —— host 半集成测试:真实 ctx.web + ctx.webServer + 真实 Config schema, 覆盖 provider 选择、轮询、结果映射、超时与 /api/tavily/usage 路由。

API Key 配置(推荐:Web 设置页)

配置路径:设置 → Tavily 搜索(settings.section 槽位,与「飞书通知」同级)。API Key 池为空或全部停用时,搜索不可用。

  • 支持添加、重命名、替换、启停和删除多个 API Key;搜索在启用且已配置的 Key 之间轮询。
  • Key 是只写控件:通过凭据服务(ctx.credentials)存储,永不写入配置文件,也不会返回浏览器。
  • 每个 Key 可以按需调用 Tavily 官方 GET /usage 查询实时积分用量、上限和搜索用量。
  • 同时可以配置 接口地址 / 搜索深度 / 最大结果数,下一次搜索立即生效。

安装

1. 打包

npm install
npm run build      # 生成 lib/client.js
npm pack           # 生成 dsh-tavily-web-search-<version>.tgz

2. 装进 profile

把 tgz 安装为 profile 的依赖,并加入 bundle 列表(否则插件的 cordis.patch.yml 不会生效):

cd "$DSH_HOME/profiles/web"
pnpm add file:/path/to/dsh-tavily-web-search-0.8.0.tgz

package.json:

"dsh": {
  "profile": {
    "bundles": [
      "@deepseek-ai/dsh-base",
      "@deepseek-ai/dsh-web-app",
      "dsh-tavily-web-search"   // ← 新增,放在 dsh-web-app 之后
    ]
  }
}

3. 迁移旧 Key 池(从 0.6.x 升级时)

0.6.x 的 Key 池存在旧的 $DSH_HOME/settings.yaml 里,0.1.7 已不再读取该文件。把该 section 原样搬进 profile 的 cordis.patch.yml(凭据引用不变,因此已存的密钥继续可用):

- id: web-search-tavily
  name: dsh-tavily-web-search
  config:
    keys:
      - id: mth3iduzu7kb77
        name: 我的
        ref: TAVILY_API_KEY_MTH3IDUZU7KB77
        enabled: false

4. 重启生效

重启 dsh web。此后模型侧每次 web_search 都会走 Tavily。

配置项

| 键 | 默认值 | 含义 | |---|---|---| | keys | [] | API Key 池的非敏感元数据;Key 值存储在凭据服务中 | | endpoint | https://api.tavily.com/search | Tavily 搜索端点 | | searchDepth | advanced | 搜索深度:basic / advanced | | maxResults | 8 | 每次搜索返回的最大结果数 | | timeoutMs | 30000 | 单次请求超时(毫秒),与调用方取消信号合并 |

验证

安装并重启后,让模型做一次 web_search(例如查一个时效性问题)。如果调用成功,说明已走 Tavily;失败时错误信息为中文且以 Tavily ... 开头。

文件

dsh-tavily-web-search/
├── package.json          # 插件清单 + bundle patch + dsh.client 声明
├── cordis.patch.yml      # 把 searchProvider 指向 tavily 并插入插件行
├── lib/
│   ├── index.js          # TavilySearchProvider 实现(host 端,手写维护)
│   ├── index.d.ts        # 类型声明
│   ├── client.js         # 浏览器端 bundle:设置页 Tavily tab(tsdown 构建)
│   └── types/client/     # 客户端类型声明
├── src/
│   ├── index.ts          # node 入口(转出 lib/index.js)
│   └── client/           # 浏览器端源码(tsdown 构建)
│       ├── index.ts      # 客户端插件主体:注册 settings.section 槽位
│       ├── service.ts    # TavilyTabController(共享表单 + 凭据/用量管理)
│       ├── TavilyTab.tsx # 设置页 Tavily 卡片 UI
│       ├── TavilyTab.module.css
│       └── locales.ts    # 中英文案(settings.tavily 命名空间)
├── scripts/
│   ├── build.mjs                # 构建包装(Windows 代码页处理)
│   ├── verify-compat.mjs        # manifest 是否通过 DSH 0.2.0 启动前置校验
│   ├── verify-client-manifest.mjs # dsh.client 声明 + 模块表请求可解析
│   ├── verify-bundle.mjs        # bundle 静态检查(handoff / 平台模块 / 无旧 API)
│   ├── verify-client.mjs        # 浏览器半运行时检查(跑真实 SettingsFormModel)
│   ├── smoke.mjs                # host 半集成测试(真实 web 缝 + webserver + 路由)
│   └── test-search.mjs          # 真实 Tavily 搜索/用量探测(需要真实凭据)
├── tsdown.config.ts      # 浏览器 bundle 配置(CSS Modules 内联)
└── README.md

开发

npm install
npm run typecheck   # tsc -p tsconfig.typecheck.json
npm run build       # tsdown → lib/client.js
npm run verify      # manifest 兼容 + 客户端清单 + bundle 静态 + 浏览器半运行时 + host 半集成
npm pack

License

MIT