Skip to content
dsh.fish
Bundle

@dshp-inx/tavily-search

Tavily AI search provider for DeepSeek Harness: replaces the official DeepSeek web search (basic/advanced depth, per-credit billing) and adds a settings page for key management and connectivity testing.

Source
Yinxe
License
MIT
Updated
Updated 2 days ago

Readme

# tavily-search

DeepSeek Harness(DSH)Web 搜索插件:用 **[Tavily](https://tavily.com) API 接管模型的 `web_search` 工具**,替换 DeepSeek 官方搜索 —— 官方搜索每次触发都消耗一轮模型调用,Tavily 更便宜、更快。密钥经 credentials 服务存入凭证库,保存后即时生效。

> 设计原则:**即插即用、零残留**。插件只注册 `tavily` 搜索提供方 + 一个设置页;API Key 每次搜索实时从凭证库解析,不滞留在提供方实例上;卸载后除凭证库里你自己存的 Key 外无任何残留。

## 功能

| 部分 | 内容 |
|---|---|
| **Host(lib/index.js)** | 注册 `tavily` WebSearchProvider 到 `ctx.web`;API Key 每次操作实时解析 `TAVILY_API_KEY`;注册四个同源 JSON 路由(`/ext/dshp-inx-tavily-search/state`、`/ext/dshp-inx-tavily-search/config`、`/ext/dshp-inx-tavily-search/test`、`/ext/dshp-inx-tavily-search/usage`,带同源校验)供设置页读写状态/搜索行为/测试连通性/用量配额 |
| **Client(client.js)** | 「设置 → Tavily 搜索」配置页:提供方状态徽章、密钥写入/显示/清除(走 api 网关 `credentials` 域)、搜索行为配置(默认结果数/搜索深度,持久化到 `settings.yaml` 的 `dshp-inx-tavily-search` 命名空间)、用量与配额卡片(Key/账号分项统计+进度条+刷新/强制刷新)、连接测试(输入查询 → 返回结果列表)。UI 全部使用 DSH 官方设计 token(`dsw-alias-*`),与官方设置页风格一致 |

搜索请求体:`api_key / query / max_results(1-10,默认走配置) / search_depth(配置:basic/advanced)/ include_answer: false`;返回统一投影为 `{ sources: [{url, title?, snippet?, publishedAt?}], truncated }`。

## 计费(按 credits,按次)

搜索按次扣 credits:**basic 1 credit/次、advanced 2 credits/次**(本插件只发
`/search`,不涉及 extract/crawl/map/research)。搜索深度保留——advanced 覆盖
更多来源,单价是 basic 的两倍,设置页下拉已标注单价。

`projectId` 配置已移除:按次计费下"按项目隔离用量"没有意义,
`X-Project-ID` 请求头与 `/usage` 的项目维度一并删掉;`settings.yaml`
里残留的 `projectId` 键会被 schema 忽略,无需手动清理。

## 用量与配额(对齐 [Usage 官方文档](https://docs.tavily.com/documentation/api-reference/endpoint/usage))

- **端点**:`GET https://api.tavily.com/usage`,鉴权为 `Authorization: Bearer <tvly-…>`(注意与 `/search` 的 `body.api_key` 不同)。
- **返回**(仅透传文档声明的叶子标量):`{ key: { usage, limit, search_usage, extract_usage, crawl_usage, map_usage, research_usage }, account: { current_plan, plan_usage, plan_limit, paygo_usage, paygo_limit, search_usage, extract_usage, crawl_usage, map_usage, research_usage } }`,其中 `limit / plan_limit` 为 `null` 表示不限量。
- **限流与缓存**:官方限流 `10 req / 10min`(开发与生产一致);服务端做 `60 秒`缓存,`GET /ext/dshp-inx-tavily-search/usage` 默认读缓存、`?force=1` 强制刷新;`429` 时返回 `ok: false` 并附带 `stale` 旧快照,设置页会明确标注“旧数据”。
- **本插件路由**:`GET /ext/dshp-inx-tavily-search/usage[?force=1]`(同源校验)→ `{ ok, usage, cached, fetchedAt, takenMs }`;`state` 另附 `usageMeta { endpoint, cacheTtlMs, rateLimit, billing, hasCache, fetchedAt }` 供设置页决定是否自动拉取。
- **错误语义**:缺 Key 提示去设置页配置;`401` 表示 Key 无效;`429` 提示稍后“强制刷新”重试;未知响应与网络失败均透出原文便于排查。

## 安装(推荐:GitHub)

```sh
dsh plugin --profile web add github:Yinxe/dsh-tavily-search
```

`dsh plugin` 把参数转发给 profile 目录里的 pnpm,装完自动把插件写进 profile 的 `dsh.profile.bundles` 挂载列表 —— **无需手动改任何配置文件**。

**一键 AI 安装**:把下面这段直接发给你的 DSH AI(复制即用,无需修改):

```text
帮我安装 Tavily 搜索插件(GitHub 仓库 Yinxe/dsh-tavily-search,包名 @dshp-inx/tavily-search):
1. 执行 dsh plugin --profile web add github:Yinxe/dsh-tavily-search
2. 检查 ~/.dsh/profiles/web/cordis.patch.yml:若已有 id: web 且带 config 的条目,给它追加 searchProvider: tavily 字段;若没有,在文件末尾追加:
   - id: web
     config:
       searchProvider: tavily
   (官方 DeepSeek 搜索与 Tavily 并存时必须显式选型,否则 web seam 抛 WEB_PROVIDER_AMBIGUOUS)
3. 重启 web 服务(dsh web),确认重启无报错
4. 告诉我如何配置 Tavily API Key(设置页入口路径 + 测试方法)
```

重启生效:

```sh
dsh web
```

**选型说明**:若你的 profile 同时启用官方搜索插件(`dsh-web-search-deepseek`),两个提供方并存时必须显式选型,在 `~/.dsh/profiles/web/cordis.patch.yml` 追加:

```yaml
# 显式选中 Tavily 作为 web 搜索提供方(否则 web seam 抛 WEB_PROVIDER_AMBIGUOUS)
- id: web
  config:
    searchProvider: tavily
```

只有一个可用提供方时 DSH 自动选中它,此选型行可省略。

**验证**:打开 web 页面 → 设置 → Tavily 搜索,能看到「Tavily AI 搜索」卡片即安装成功。

## 配置密钥

1. 注册 [tavily.com](https://tavily.com)(有免费额度),取 `tvly-…` 格式的 API Key;
2. 设置 → Tavily 搜索 → 粘贴密钥 → 保存密钥。「API Key」行变绿(已配置)、「搜索引擎」行显示「Tavily · 当前生效」即接管完成;
3. 在连接测试框输入任意查询点「运行测试」,返回结果列表即全链路通。

密钥通过 DSH credentials 服务持久化到 `~/.dsh/.credentials.yaml`,**不回显、不进模型上下文**;写入/清除即时生效,无需重启。

## 更新

```sh
dsh plugin --profile web update "@dshp-inx/tavily-search" --latest
dsh web
```

`update --latest` 会让 pnpm 重新解析 GitHub 仓库的最新 commit 并更新 lockfile;重启后生效。

## 安装(备选:clone 源码 + 本地 link)

适合想改源码、或 GitHub 不可达的场景。clone 后用 `add ./<目录>` 安装 —— **依赖按插件真实包名(`@dshp-inx/tavily-search`)登记**,后续 update / remove 与 GitHub 安装完全一致。link 安装的源码改动**即时生效**(client 半刷新页面即可,host 半需重启 `dsh web`):

```sh
git clone git@github.com:Yinxe/dsh-tavily-search.git ~/.dsh/plugins/tavily-search
cd ~/.dsh/plugins
dsh plugin --profile web add ./tavily-search
dsh web
```

> `add ./<目录>` 的相对路径按**你执行命令时所在的目录**解析,先 `cd` 到插件目录的父级再执行。
> ⚠️ **不要直接编辑 `node_modules/@dshp-inx/tavily-search/` 里的文件**:pnpm 的安装文件与内容寻址 store 硬链接,直接覆盖会连带改坏 store。改源码请改 clone 出来的源码目录。

link 方式的更新就是 `git pull`(源码目录)+ 刷新页面/重启。

## 卸载

```sh
dsh plugin --profile web remove "@dshp-inx/tavily-search"
```

`remove` 会自动从 `dsh.profile.bundles` 撤下挂载。收尾:

1. 若曾加过 `web.searchProvider: tavily` 选型行,删除它(否则指向不存在的提供方);
2. (可选)清除密钥:设置页点「清除密钥」;
3. `dsh web` 重启;clone 安装的再删掉 `~/.dsh/plugins/dsh-tavily-search` 目录即可。

## 配置(标准 settings 存储)

搜索行为持久化到 `settings.yaml` 的 `dshp-inx-tavily-search` 命名空间,设置页改完即时生效,外部编辑热重载(密钥仍走凭证库,不进 settings):

```yaml
dshp-inx-tavily-search:
  maxResults: 5      # 默认结果数 1–10
  searchDepth: basic # basic(1 credit/次)| advanced(2 credits/次)
```

> v1:本命名空间曾有 `projectId` 字段(透传 `X-Project-ID` 按项目隔离用量),
> v2 按次计费下无意义已移除。残留键会被 schema 忽略,无需手动清理。

`cordis.patch.yml` 的 `config:` 仍可覆盖默认值(settings 的 base 层)。单次搜索可传 `maxResults` 覆盖本次默认值。

## 常见问题

- **报「Tavily 搜索缺少 API Key」**:设置页配置密钥,或检查 `~/.dsh/.credentials.yaml` 是否有 `TAVILY_API_KEY`。
- **用量卡片一直转圈/报 429**:官方限流 10 次/10 分钟,服务端有 60 秒缓存;等 1 分钟后点「强制刷新」,或减少刷新频率。429 时会显示旧快照并标注“旧数据”。
- **用量与预期对不上**:检查 Tavily 控制台的计费口径(搜索按 credits:basic 1/次、advanced 2/次)。注意 `/logs` 另需付费计划,免费账号调日志接口会 `403`,与本插件无关。
- **`WEB_PROVIDER_AMBIGUOUS`**:patch 层缺 `web.searchProvider: tavily` 选型行。
- **设置页没有这张卡片**:确认 profile `package.json` 的 `dsh.profile.bundles` 含 `@dshp-inx/tavily-search`,且依赖已装上。
- **测试报 403**:路由带同源校验(`Origin` 必须与 `Host` 一致或缺失),经非同源代理访问会拒绝 —— 直接从浏览器访问 web 端口即可。

## 代码结构

```
lib/index.js     Host 半:tavily 搜索提供方 + 四个同源 JSON 路由(state/config/test/usage)+ settings 持久化
lib/shared.js    Host 三件套(settingsNamespace/json/sameOrigin/readBody,六插件逐字相同)
client.js        Client 半:__ModuleLoader__ bundle,设置页 UI(状态/密钥/搜索行为/用量配额/连接测试,DSH 官方设计 token)
cordis.patch.yml bundle 层 patch:仅 insert 挂载行
```

## 免责声明

- 搜索能力与配额由 [Tavily](https://tavily.com) 提供,密钥与计费归你自己的账号;
- 本插件与 Tavily、DeepSeek 官方均无隶属关系;API 用法以 [Tavily 文档](https://docs.tavily.com) 为准。

Install

dsh plugin --profile web add github:Yinxe/dsh-tavily-search

Profile: web

  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source