Skip to content
dsh.fish
Bundle

dsh-tavily-provider

Tavily-backed web_search / web_fetch providers for DeepSeek Harness — replaces the built-in DeepSeek search backend.

Source
MirrMeur
License
MIT
Updated
Updated 3 hours ago

Readme

# dsh-tavily-provider

给 DeepSeek Harness 的 **Tavily 版 web_search / web_fetch 后端**:把内置的 DeepSeek 搜索换成 Tavily,
用你已有的 `TAVILY_API_KEY`(存在凭证里)作答。

零依赖、零 import:整个插件不 import 任何 `@deepseek-ai/*`,只用宿主注入的 `ctx` 和全局 `fetch`。
因此它同时适用于 **0.1.1-rc.x 和 0.1.5 线**,也不会因为客户端/设置 API 改名而失效
(0.1.5 删掉了 `@deepseek-ai/dsh-client-runtime`,并从 `dsh-settings` 移除了
`installSettingsSection` / `settingsNamespace` —— 本插件两者都不碰)。

## 为什么需要它

社区插件 `@dsh-external/dsh-plugin-tavily@0.6.2` 在 0.1.5 上**会让整个 profile 起不来**:

```
dsh-plugin-tavily@0.6.2 → "@deepseek-ai/dsh-settings" 不再导出 installSettingsSection / settingsNamespace
dsh: plugin tree failed to load → exit 1
```

上游没有 0.1.5 适配版(作者 CI 矩阵封顶 0.1.1-rc.2)。本插件沿用**完全相同的 provider id**,
所以升级后 profile 里那两行配置原样即可:

```yaml
- id: web
  config:
    searchProvider: tavily
    fetchProvider: tavily-extract
```

## 安装

```sh
# 从 GitHub 直接装(推荐)
dsh plugin --profile web add github:MirrMeur/dsh-tavily-provider

# 钉住某个 tag / commit(更可复现)
dsh plugin --profile web add github:MirrMeur/dsh-tavily-provider#v0.1.0

# 本地目录开发用(link 挂载,改文件后重启即生效)
dsh plugin --profile web add file:/path/to/dsh-tavily-provider
```

装完**重启该 profile 的 Harness 进程**(不是刷新浏览器),再确认 `cordis.patch.yml` 里有上面那两行。

## 更新

git 依赖在 spec 不变时 pnpm 可能报 `Already up to date` 而不刷新,强制重解析一次:

```sh
cd ~/.dsh/profiles/web          # 或 $DSH_HOME/profiles/web
pnpm up dsh-tavily-provider
```

或改钉 tag 重装:

```sh
dsh plugin --profile web add github:MirrMeur/dsh-tavily-provider#v0.2.0
```

## 配置

全部可选,写在 profile 的 `cordis.patch.yml` 里,按 entry id 定位:

```yaml
- id: tavily-provider
  config:
    maxResults: 5          # 1..20,web_search 未显式传 maxResults 时的默认值
    searchDepth: basic     # basic | advanced
    topic: general         # general | news
    apiKeyEnv: TAVILY_API_KEY   # 凭证名;默认就是它
    apiKey: <literal>      # 一般不填:明文落盘,优先级最高
    baseURL: https://api.tavily.com
```

**API key 解析顺序**:`apiKey` 字面量 → 凭证服务 `ctx.get("credentials").resolve(apiKeyEnv)`
(即 `~/.dsh/.credentials.yaml` 里的 `TAVILY_API_KEY`)→ 进程环境变量 `TAVILY_API_KEY`。
都没有时走 Tavily keyless(匿名限额,够轻量用)。

## 行为

| 能力 | provider id | 说明 |
|---|---|---|
| `web_search` | `tavily` | `POST /search`;把 `results[]` 映射成 `{url, title, snippet, publishedAt}` |
| `web_fetch` | `tavily-extract` | `POST /extract`(markdown),映射成 `{url, statusCode, body:{kind:"text",content}}` |

失败语义跟随宿主 seam:网络/超时 → `WEB_PROVIDER_ERROR`(消息里带 HTTP 状态与凭证名提示),
调用方取消 → `WEB_ABORTED`。

## 自查

```sh
node test/smoke.mjs     # 10 项:映射、clamp、keyless、凭证/环境回退、401、abort、注册
```

真实接口冒烟(会消耗一次 Tavily 配额):

```sh
TAVILY_API_KEY=... node -e '
import("./lib/index.js").then(async (m) => {
  const key = process.env.TAVILY_API_KEY;
  const ctx = { get: (s) => s === "credentials" ? { resolve: async () => ({ value: key }) } : undefined };
  const p = new m.TavilySearchProvider(() => ({ ctx, config: { maxResults: 3 } }));
  console.log(await p.search({ query: "DeepSeek Harness" }));
});'
```

## 已验证

- 10 项单测(stub fetch)
- 真实 Tavily API:`/search` 返回 3 条(含标题/URL/snippet),`/extract` 返回 19k 字符正文
- 隔离宿主 **DeepSeek Harness 0.1.5-rc.2**:profile 启动正常,headless 下 `web_search` 实际由本 provider 作答

## 局限

- 没有设置卡片(设置页 UI)。配置走 `cordis.patch.yml`;旧插件的卡片在 0.1.5 上本来就不可用。
- `web_fetch` 只支持文本/markdown,不做图片、PDF 解析。
- 未实现 `firecrawl`(旧插件里的第三后端,实际未启用)。

## License

MIT

Install

dsh plugin --profile web add github:MirrMeur/dsh-tavily-provider

Profile: web

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