Skip to content
dsh.fish
Bundle

@my-dsh/dsh-web-search-tavily

Tavily-backed search provider for the DeepSeek Harness web capability seam (ctx.web): registers the `tavily` search provider so the model-facing web_search tool resolves it

Source
my-dsh
stars
1 stars
License
MIT
Updated
Updated yesterday

Readme

# dsh-web-search-tavily

[English](README.en.md) | 中文

[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 的 Tavily 联网搜索插件。

该插件向 `web` 能力缝(`ctx.web`)注册一个 Tavily 后端的搜索 provider,并把 `web_search` 工具的搜索选择切到它。注册后,模型每次调用 `web_search` 都会通过 Tavily REST API(`POST /search`)执行联网检索,返回标题、链接和页面摘要。

## 为什么需要它

DSH 自带的搜索 provider 是 `deepseek-official`,它通过 DeepSeek API 的服务端检索执行搜索,消耗的是模型 API 的计费额度。Tavily 是独立的搜索 API,有自己的免费/廉价配额(`basic` 档每次 1 credit),适合把「聊天计费」和「联网搜索用量」分开,或单独控制搜索配额。

## 安装

需要一个 web surface profile(`dsh web` 的默认 profile 名是 `web`)。需要 `git` 和 `pnpm` 都在 `PATH` 上。

```sh
# 从 GitHub 直装(需要 git 和 pnpm 都在 PATH 上;用已存在的 web surface profile 名替换 <name>,缺省 web surface profile 就叫 `web`)
dsh plugin --profile web add github:my-dsh/dsh-web-search-tavily

# 或安装已发布到 npm 的版本
dsh plugin --profile web add @my-dsh/dsh-web-search-tavily
```

包声明了 `dsh.bundle`,安装后自动加入 profile 的 bundle 层栈,重启 DSH 生效。

### 前置条件

- DSH `0.1.2-alpha.2` 或更高(插件通过 settings 服务注册配置段;更早版本没有该服务侧 API)。
- 一个 web surface profile(如 `dsh web` 使用的默认 `web` profile)。
- Tavily API key,二选一:
  - **写入 DSH 凭据文件**(推荐):编辑 `~/.dsh/.credentials.yaml`,在 `refs:` 下加一行 `TAVILY_API_KEY: tvly-...`(store 会自动重载);或
  - 在启动 DSH 的环境里 `export TAVILY_API_KEY=tvly-...`。

key 按**每次搜索**解析一次(凭据服务优先,回落到启动环境),从不缓存、从不落盘到配置文件。

### bundle 补丁做了什么

`cordis.patch.yml` 两行:

1. 插入 `@my-dsh/dsh-web-search-tavily`——注册 id 为 `tavily` 的搜索 provider;
2. 把 `web` 行的 `searchProvider` 改成 `tavily`。补丁是整体替换 `config`,所以同时复述了 dsh-base 自带的 `fetchProvider: http`(否则匿名 fetch 会被关掉)。

## 配置

全部可选。通过用户 patch 层(`~/.dsh/profiles/<name>/cordis.patch.yml`)覆盖:

```yaml
- id: web-search-tavily
  name: '@my-dsh/dsh-web-search-tavily'
  config:
    # 搜索深度:basic(1 credit,默认)或 advanced(2 credits)
    searchDepth: advanced
    # 无 maxResults 的请求向 Tavily 要多少条结果(默认 8)
    maxResults: 5
    # 单次请求超时毫秒(默认 30000)
    timeoutMs: 20000
    # API key。留空走凭据/环境解析(推荐);填了则字面量优先,密钥会进入配置文件
    # apiKey: tvly-...
```

| 字段 | 默认 | 说明 |
|---|---|---|
| `apiKey` | — | 字面量 key;优先于凭据解析。建议留空 |
| `apiKeyEnv` | `TAVILY_API_KEY` | 凭据名 / 环境变量名 |
| `baseURL` | `https://api.tavily.com` | REST 端点,`/search` 会拼在后面 |
| `searchDepth` | `basic` | Tavily `search_depth` |
| `maxResults` | `8` | 默认结果数上限 |
| `timeoutMs` | `30000` | 每次请求超时 |

设置页修改即时生效:provider 按搜索快照当前配置段,一次搜索不会混用两个版本的配置。

## 行为细节

- **凭据解析失败、Tavily 返回错误、网络失败、超时**都以 DSH 标准 `WebError` 上抛,携带结构化码(`WEB_PROVIDER_CREDENTIAL_MISSING` / `WEB_PROVIDER_ERROR` / `WEB_ABORTED`),与自带 provider 走同一条 `WebError` 类,工具层因此能保留 `{name, code}` 结构化元数据。
- **取消**:调用方信号(工具超时、模型主动取消)与本插件的 `timeoutMs` 合并为一个 `AbortSignal.any`,先到先生效——取消能真正终止在途的 HTTP 请求,而不是等它跑完。
- **超时分类**:本插件自身超时以 `WEB_PROVIDER_ERROR` 上抛(消息含 `timed out after Nms`),与自带搜索 provider 的行为一致;调用方取消则归类为 `WEB_ABORTED`。
- **字面量 `apiKey` 优先**:配置了 `apiKey` 时不再经过凭据解析,直接使用。
- **去重**:Tavily 返回的重复 URL 会按序去重。
- **可移植源结构**:结果映射为 `{ url, title?, snippet?, publishedAt? }`,与 `web` 缝的其他 provider 一致。

## 源码布局

```
dsh-web-search-tavily/
├── src/
│   ├── index.js    # Cordis 函数插件:Config schema + 注册进 ctx.web
│   └── provider.js # TavilySearchProvider:REST 映射、错误码、去重、超时
├── cordis.patch.yml  # bundle 补丁:插入 provider + 切换 web.searchProvider
└── package.json      # dsh.bundle 声明 + peer 依赖
```

纯 ESM JavaScript,无构建步骤,TypeScript 类型通过 JSDoc 标注。

## 发布到 npm

要把本包发布到 npm,需要一个能读写 `@my-dsh` scope 的 npm 账号和一台已登录 npm 的机器。`package.json` 里已设置 scoped 包约定(`publishConfig.access: public`),维护者只需执行:

```sh
npm login                       # 用 @my-dsh scope 对应的账号登录
npm publish
```

仓库根的 `.npmrc` 已把 registry 钉在 `https://registry.npmjs.org/`,发布机器上无需再手工切换;npm 会读取它而不是镜像配置。

`npm pack --dry-run` 可预览实际 tarball 内容(`files` 白名单发布 `src/`、bundle 补丁、两份 README 和 `LICENSE`)。发布成功后,用户可用 `dsh plugin --profile <name> add @my-dsh/dsh-web-search-tavily` 安装。GitHub 与 npm 两条渠道的安装命令都有效,但 README 无法区分当前哪条生效,请以包页面标注的渠道为准。

## License

[MIT](LICENSE)

Install

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

Profile: web

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