@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,无需新工具。
Maintainers
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.yaml 的 web-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-config 看 web 行的 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
