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-search-failover

v0.3.9

Published

Provider-level web search+fetch pool for DeepSeek Harness: bypass the official LLM search channel (0 model tokens), failover/rotate across Exa/Tavily/Jina/Firecrawl/Serper/SerpApi/SearXNG/DDG/Brave with quota-aware circuit breaking, multi-key rotation, an

Readme

dsh-search-failover


为什么不用官方默认搜索?

DSH 默认通道 deepseek-official 不是专用搜索 API:每次 web_search 都会发起一轮完整 Messages 模型调用,由 DeepSeek 在服务端执行搜索。这意味着:

| | 官方 deepseek-official | 本插件 search-pool | |---|---|---| | 检索方式 | 一整轮 LLM 调用 + 服务端 web_search 工具 | 直连 Exa / Tavily / Jina / Firecrawl 等检索端点 | | 模型 token | 每次搜索都烧(input + output),结果还会回灌上下文 | 0(纯检索,不碰任何 LLM) | | 计费来源 | DEEPSEEK_API_KEY 余额 | 各引擎自己的免费额度 | | 抓取 web_fetch | 同样走官方通道 | 同步接管:Jina Reader / Exa Contents / Tavily Extract / Firecrawl Scrape | | 宕机 / 额度耗尽 | 整条链路挂掉 | 熔断冷却 + 自动下探下一个引擎 / 下一个 Key |

装上即把 searchProviderfetchProvider 都指到 search-pool。卸载后自动回落到官方通道。


✨ 核心特性

  • 🛡️ Provider 级透明替换:无侵入接管 DSH ctx.web搜索 + 抓取,保持原生 web_search / web_fetch 工具签名不变。
  • 🔄 双重路由策略
    • 优先顺序 (Failover):按优先级从高到低依次尝试,前一个后端失败或熔断自动下探下一个。
    • 加权轮询 (Weighted Rotate):按 1~10 权重将搜索流量平摊到所有健康引擎,最大化榨干各大搜索源的免费额度。
  • 智能额度感知与熔断器 (Circuit Breaker)
    • 遇到额度耗尽(HTTP 402/429/Quota Exceeded)→ 长冷却 (1h),避免无效请求;
    • 遇到临时网络抖动(Transient Error)→ 5 分钟内连续 3 次失败触发 短冷却 (60s)
    • 冷却到期自动半开探活,成功立即恢复。
  • 🤖 AI 自主换源技能 (web_search_from)
    • 为 Agent 注入专属换源工具。当 AI 认为默认结果不够理想、信息过时或源单一时,可自主选择 exa / serper / tavily / jina / firecrawl 等引擎重新搜索并对比。
  • 🎛️ 现代卡片流 Web GUI 设置面板
    • 在 DSH 设置页一键填写/修改 API Key、切换策略、拖拽排序、测试连通性,保存即实时生效,无需重启进程
    • 密钥安全保存在本地 ~/.dsh/settings.yaml,绝不上报。
  • 🔑 单引擎多 Key 轮换:同一后端可换行或逗号填多个 Key;Key A 额度耗尽先切 Key B,全部挂了才熔断下探下一个引擎。
  • 🔌 全生态适配
    • 搜索:Exa, Serper, Tavily (keyless 匿名档), Jina, SerpApi, Firecrawl, SearXNG (自托管), DuckDuckGo, Brave
    • 抓取:Jina Reader (r.jina.ai) · Exa Contents · Tavily Extract · Firecrawl Scrape

🏗️ 架构概览

┌──────────────────────────────────────────────────────────────┐
│                    AI Agent / User Chat                      │
└──────────────┬────────────────────────────────┬──────────────┘
               │ (默认搜索 / 抓取)                │ (显式换源)
               ▼                                ▼
┌──────────────────────────────┐ ┌─────────────────────────────┐
│  原生 web_search / web_fetch  │ │  web_search_from (增强工具)   │
└──────────────┬───────────────┘ └──────────────┬──────────────┘
               │                                │
               ▼                                ▼
┌──────────────────────────────────────────────────────────────┐
│               SearchPoolProvider (search-pool)               │
│                                                              │
│  [调度决策]                                                   │
│   ├── 指定源 (source): 直连指定引擎, 不走池                      │
│   ├── Failover: 按 priority 升序依次尝试                       │
│   └── Rotate: 按 weight 展开加权轮转                           │
│                                                              │
│  [熔断与健康守护]                                              │
│   ├── CircuitBreaker 监控各后端健康度                          │
│   └── 额度耗尽(1h 冷却) / 瞬时错误(60s 冷却) / 探活恢复           │
└──────────────────────────────┬───────────────────────────────┘
                               │
   ┌──────────┬──────────┬─────┴────┬──────────┬──────────┬──────────┐
   ▼          ▼          ▼          ▼          ▼          ▼          ▼
┌─────┐    ┌──────┐   ┌──────┐   ┌──────┐   ┌─────────┐┌─────┐   ┌─────────┐
│ Exa │    │Serper│   │Tavily│   │ Jina │   │Firecrawl││Serp-│   │ SearXNG │
│     │    │ .dev │   │(Anon)│   │  AI  │   │ .dev    ││ Api │   │ (Local) │
└─────┘    └──────┘   └──────┘   └──────┘   └─────────┘└─────┘   └─────────┘

🎛️ 设置面板实机预览

  • 实时密钥填写:随时填写或更新各引擎 API Key(支持多行多 Key),点击保存立即热生效。行内「↗」直达各引擎申请页。
  • 网页抓取接管web_fetch 同步走搜索池(Jina Reader / Exa / Tavily / Firecrawl),享受同一套熔断与多 Key。
  • 一键测试连接 (▶ 测试):对指定后端发起 1 条测试搜索,毫秒级反馈连通状态与响应耗时。
  • 动态优先级调整 (↑ / ↓):通过按钮调整引擎在 Failover 链中的优先级。
  • 轮询权重调节:在轮询分摊模式下,为不同引擎设置 1~10 权重值。
  • 添加自定义后端:无需改写代码或配置文件,直接在界面添加 SearXNG 实例或新后端。
  • 额度余量透视:行内直接显示支持额度查询的后端(如 SerpApi)的套餐类型、剩余次数及重置日期。

🚀 快速开始

1. 安装插件

在你的 DSH 项目或 Web Profile 下安装:

# 方式 A: 从 npm 安装 (推荐)
dsh plugin --profile web add dsh-search-failover

# 方式 B: 本地克隆软链调试 (开发者)
git clone https://github.com/Walvez/dsh-search-failover.git
dsh plugin --profile web add link:$(pwd)/dsh-search-failover

2. 启用配置

cordis.patch.yml 中声明挂载与默认后端配置:

- id: search-pool
  name: dsh-search-failover
  config:
    strategy: failover          # failover (优先顺序) | rotate (轮询分摊)
    maxResults: 8               # 默认返回条数上限
    timeoutMs: 15000            # 单个请求超时时间 (ms)
    backends:
      - id: exa
        kind: exa
        apiKeyEnv: EXA_API_KEY  # 从 ~/.dsh/.env 读取
        priority: 1
      - id: serper
        kind: serper
        apiKeyEnv: SERPER_API_KEY
        priority: 2
      - id: tavily
        kind: tavily
        apiKeyEnv: TAVILY_API_KEY
        priority: 3
      - id: jina
        kind: jina
        apiKeyEnv: JINA_API_KEY
        priority: 4
      - id: firecrawl
        kind: firecrawl
        apiKeyEnv: FIRECRAWL_API_KEY
        priority: 5
      - id: serpapi
        kind: serpapi
        apiKeyEnv: SERPAPI_API_KEY
        priority: 6
      - id: searxng
        kind: searxng
        baseURL: http://127.0.0.1:8080
        priority: 7
    circuit:
      threshold: 3              # 连续错误阈值
      burstWindowMs: 300000     # 统计时间窗口 (5 分钟)
      cooldownMs: 60000         # 瞬时错误冷却时间 (1 分钟)
      quotaCooldownMs: 3600000  # 额度耗尽冷却时间 (1 小时)

3. 启动 DSH Web

dsh web

打开 Web GUI (默认 http://127.0.0.1:3080),进入 设置 → 搜索池 即可在界面直接管理所有 Key。


📊 后端引擎支持与额度参考

| 引擎标识 (kind) | 搜索 | 抓取 | 官方免费额度 (核实) | 密钥 | 申请页 | |---|:---:|:---:|---|---|---| | exa | ✓ | ✓ | 注册送 $20,每月赠 $10 | 必须 | dashboard.exa.ai | | serper | ✓ | ✗ | 注册赠送 2,500 次 | 必须 | serper.dev | | tavily | ✓ | ✓ | 每月 1,000 credits;无 key 走匿名档 | 可选 | app.tavily.com | | jina | ✓ | ✓ | 免费注册 Key;s.jina.ai 搜索 / r.jina.ai 抓取 | 必须 | jina.ai | | firecrawl | ✓ | ✓ | 每月 1,000 credits | 必须 | firecrawl.dev | | serpapi | ✓ | ✗ | 每月 250 次,支持实时额度查询 | 必须 | serpapi.com | | searxng | ✓ | ✗ | 自托管无限 | 无 | docs.searxng.org | | brave | ✓ | ✗ | 需绑卡 | 必须 | brave.com/search/api | | ddg | ✓ | ✗ | 完全免费 | 无 | — |

同一后端可换行或逗号填多个 Key。Key A 额度耗尽先切 Key B,全部挂了才熔断下探下一个引擎。


🤖 AI 自主换源工具 (web_search_from)

当 Agent 认为默认搜索结果不理想时,可以主动调用由本插件注册的 web_search_from 工具:

工具参数

{
  "name": "web_search_from",
  "description": "用指定的搜索后端(引擎)搜索当前信息并返回该源原始结果。可用于多源对比或换引擎重试。",
  "parameters": {
    "query": { "type": "string", "description": "搜索关键词" },
    "source": { "type": "string", "description": "指定后端类型 (例如 exa, serper, tavily, jina, firecrawl, searxng 等)" },
    "maxResults": { "type": "number", "description": "返回结果数量上限 (默认 8)" }
  }
}

Agent 典型工作流

  1. Agent 执行 web_search(query="最新技术动态") 走默认搜索池;
  2. 发现结果大多是旧闻或不相关,Agent 主动调用 web_search_from(query="最新技术动态", source="serper") 从 Google 实时索引获取结果;
  3. 对比各源信息,输出最准确、最及时的回答。

🧪 单元测试

项目包含完善的单元测试套件(覆盖熔断器状态机、加权轮询、优先级排序、多源容灾、自愈探活等):

# 运行单元测试
npm test

# 运行真实网络冒烟测试
EXA_API_KEY=your_key node scripts/smoke.mjs exa serper tavily

📄 开源许可证

本项目基于 MIT License 开源。

欢迎提交 Issue 和 Pull Request 共同改进!