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

@mikasomaka/dsh-web-search

v0.1.3

Published

多 provider 顺序链的 web_search 后端(DeepSeek Harness 插件):给内置 web_search 工具注册一个 chain provider,按顺序回退 Gemini(Google Search grounding)、Exa、Firecrawl。key 与配置全在 ~/.dsh/settings.yaml,复用内置工具的 schema/渲染/UI,无需新工具。

Readme

dsh-web-search

多 provider 顺序链的 web_search 后端 —— DeepSeek Harness (dsh) 插件

npm 包名:@mikasomaka/dsh-web-search

给 dsh 内置的 web_search 工具注册一个 id 为 chain 的搜索 provider,内部按配置顺序(默认 Gemini → Exa → Firecrawl)依凭据可用性选择第一个 provider 执行搜索;选中者失败/超时/返回空结果时自动回退到下一个。工具的 schema、渲染、UI 卡片全部复用 dsh 内置实现,无需新增任何模型可见工具

特性

  • 🔗 顺序链:gemini → exa → firecrawl,按凭据可用性取第一个,可自定义顺序
  • 🛡️ 自动回退:选中 provider 失败/超时/空结果时回退下一个(fallbackOnError: true
  • 🔑 凭据灵活:key 放 ~/.dsh/settings.yaml,或环境变量 / 凭据缝(apiKeyEnv
  • 🧩 零新工具:复用内置 web_search,无需改模型侧任何东西
  • 零配置可诊断:未配置 key 时报可操作错误,告诉你该填什么、填在哪

安装

# 在你的 dsh 仓库根目录(有 pnpm dsh 的地方)
pnpm dsh plugin --profile web add @mikasomaka/dsh-web-search

然后让 web_search 选中 chain provider(编辑 profile 的用户 patch 层 cordis.patch.yml):

- id: web
  config:
    searchProvider: chain

备选:不写 patch,启动 dsh 前设置环境变量 $DSH_WEB_SEARCH_PROVIDER=chain 同样生效。

安装后重启 web 服务器生效。

配置(settings.yaml)

所有 key 与选项都在 ~/.dsh/settings.yamlweb-search: 段(热生效,无需重启):

web-search:
  order: [gemini, exa, firecrawl]   # 链顺序(按凭据可用性取第一个;热修改即时生效,无需重建链)
  fallbackOnError: true             # 失败/超时/空结果时回退下一个(默认 true)
  timeoutMs: 30000                  # 回退模式下每次尝试的超时(毫秒)
  maxResults: 5                     # 链级每个 provider 的请求上限(可选;与 web_search 自带 searchMaxResults 取 min)
  gemini:
    apiKey: '<你的 GEMINI_API_KEY>'  # 或 apiKeyEnv: GEMINI_API_KEY(环境变量/凭据缝)
    model: gemini-3.5-flash-lite
    baseUrl: https://generativelanguage.googleapis.com
    maxOutputTokens: 2048           # 注意: 1024 会让该端点返回退化空响应,勿改小
  exa:
    apiKey: '<你的 EXA_API_KEY>'
    apiURL: https://api.exa.ai/search
    searchType: auto                # auto | keyword | neural
    allowKeyless: false             # true 时无 key 走匿名 MCP(限流,不建议)
  firecrawl:
    apiKey: '<你的 FIRECRAWL_API_KEY>'
    baseURL: https://api.firecrawl.dev/v2
    allowKeyless: false             # true 时无 key 走 keyless 模式(限流,不建议)

key 解析顺序:settings 字面量 apiKey → 凭据缝 → 启动环境 → 进程环境(apiKeyEnv 指定环境变量名)。

只配置其中一家的 key 也行——链会自动跳过没有 key 的 provider。

Provider 说明

| Provider | 认证方式 | 端点 | 输出特点 | |---|---|---|---| | Gemini | x-goog-api-key | generativelanguage.googleapis.com/v1beta/models/{model}:streamGenerateContent?alt=sse | 生成式回答 + grounding 来源(title 为域名) | | Exa | x-api-key | api.exa.ai/search | 每条带摘要 + 发布日期 | | Firecrawl | Bearer | api.firecrawl.dev/v2/search | 每条带描述片段(HTML 实体已解码) |

常见问题

Q: 装完没配任何 key,会怎样? A: web_search 报可操作错误:No web search provider has credentials configured (chain: gemini → exa → firecrawl). Set keys in settings.yaml (web-search.gemini/exa/firecrawl.apiKey) or the corresponding env vars. —— 按提示填 key 即可。

Q: 装了插件但 web_search 好像没变化? A: 检查 searchProvider: chain 是否生效(pnpm dsh --profile web --dump-configweb 行的 searchProvider)。没改的话 web_search 仍走内置 deepseek-official,与本插件无关。

Q: Gemini 偶尔返回空结果? A: 已知该端点偶发退化响应(纯空白内容 + 0 来源)。已处理:provider 层视为空并抛错,chain 层(fallbackOnError: true)自动回退到 exa / firecrawl。

Q: Gemini 一直很慢或超时? A: Gemini 搜索延迟波动大(5~60s)。链内每次尝试默认 30s 超时,超时自动回退。若你的场景 Gemini 经常超时,可调大 timeoutMs,或在 order 里把更快的 provider 排前面。

开发

TypeScript + tsdown + vitest 工程化(TS 7 / Node ≥ 18.17):

pnpm install        # 安装 devDeps(typescript/tsdown/vitest/@deepseek-ai 类型)
pnpm typecheck      # TS 7 类型检查(strict)
pnpm test           # vitest 单元测试(mock fetch,无网络)
pnpm build          # tsdown(Rollup 内核)打包 src/ → lib/,自动生成 .d.ts
npm publish         # 发布(prepublishOnly 自动 build + typecheck + test)
  • src/providers.ts — 三个独立 provider + chain(WebSearchProvider 接口,fetch 可注入)
  • src/index.ts — 插件入口(Config schema + apply + ctx.web.registerSearchProvider
  • tests/ — vitest 测试:provider 请求/映射断言 + chain 回退逻辑 + settings 异步 attach 时序回归
  • scripts/live-test.mjs — 真实 key 线上验证(key 从环境变量读,不硬编码),pnpm test:live
  • 构建产物 lib/index.mjs + lib/index.d.mts@deepseek-ai/* 保持 external,由宿主解析)

License

MIT