dsh-serper-search
Complementary web-search provider: every web_search merges the DeepSeek Search API (primary) with serper.dev Google results (secondary) at a fixed 2:1 ratio. Both sides are direct HTTP retrievals with no auxiliary model turn: URL-deduped sources, long DeepSeek summaries clipped into snippets, per-ba
Install
dsh plugin --profile web add dsh-serper-search
Sandbox test results
| Stage | Result |
|---|---|
| 1 install | ✓ |
| 2 list | ✓ |
| 3 mount | ✓ |
| 4 boot | — |
Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).
README
dsh-serper-search
DeepSeek Search API(官方自研搜索引擎)+ serper.dev(Google 搜索)双擎互补,并可选接入腾讯云元宝搜索(WSA SearchPro)作为第三路,接入 DeepSeek Harness 的 web 能力缝(ctx.web)。安装后,DSH 内置的 web_search 每次发 1~3 次直连检索请求(native:true 且各路可用时两路;yuanbaoEnabled: true 时三路;缺 key 或 native:false 时相应减少,均无辅助模型调用),结果按 URL 去重、再过质量规则,以固定比例交错(两路默认 2:1;三路 '1:1:1')合并,让模型同时拿到 DeepSeek 自有索引、Google 索引与元宝的官方长尾页。
为什么互补:实测同一组 query 下,DeepSeek Search API 与 Google 的结果 URL 重叠仅 1.3%(同后端重复调用噪声地板 43%–100%,故为真实索引差异)。DeepSeek 侧更快、更贴中文,Google 侧覆盖面更广,两者互补而不互相替代。
v3 不再调用 DeepSeek 原生 Messages 搜索(旧版那一半每次要一整轮模型调用 5.3s / 0.019 元,且返回的是无摘要裸链接)。
v0.4.0 起:成功结果默认缓存 5 分钟(同一 query 重复搜索 0 上游请求)、单路失败按类型冷却并在降级时给模型一行 Note:、设置页多出「测试各路 / 检查更新 / 设为本机默认搜索 / 恢复部署默认」四个按钮;v0.5.0 起设置页改成「三个搜索源各自一组」(各组独立开关 / 凭据 / 参数,见 [GUI 设置页](#gui-设置页)),并支持三路 8 + 8 + 8(searchMaxResults: 24);安装后不再需要手改 cordis.patch.yml——首次启动会自动把 searchProvider 指向本插件(写入位置与撤销方式见[卸载与恢复](#卸载与恢复))。
截图
市场详情页的画廊由仓库根的screenshots.json声明、夜间构建自动抓取(无需向市场仓库提 PR);图片本身是assets/shot-settings.png与assets/shot-merged.png。
给 AI 的一句话(最快安装)
把这句话原样发给你的 DSH:
安装 dsh-serper-search 并跑一次双路自检,把结果告诉我
Agent 可以按下面五步执行(这也是本节存在的意义:把「装完怎么确认生效」变成一段可复制的话):
1. 安装:dsh plugin --profile web add dsh-serper-search;
2. 配 key(没有 serper key 也能装,只是退化为官方单路):~/.dsh/.credentials.yaml 的 refs: 下加 SERPER_API_KEY: <key> 与 DEEPSEEK_API_KEY: <key>;
3. 重启 dsh web(首次启动会写 pin),再确认:dsh --profile web --dump-config | grep -A4 "^- id: web$",应看到 searchProvider: serper;
4. 新会话调用一次 web_search,确认返回 ≥1 条来源;日志(前缀 web-search-serper:)里应有 merged= 与 cache=store;
5. 「测试各路」是 GUI 里的按钮(POST /api/dsh-serper-search/probe):打开 设置 → 插件 → dsh-serper-search 点一下,把结果行(1234ms · 3)或错误分类贴回来。Agent 若不能操作浏览器,第 4 步的真实搜索就是验收。
人工验收同样适用:装 → 搜 → 点自检,三步内跑通。若第 4 步结果里出现 Note: serper auth failed ...,说明 serper key 没配好——在卡片里补填或改 key 后冷却立即清除,不需要等冷却到期(auth/quota 10 分钟、rate-limit/server 60 秒、timeout/network 30 秒)。
安装
dsh plugin --profile web add dsh-serper-search
或打开 设置 → 插件市场,搜索 dsh-serper-search 一键安装。
1. 配置两个 key(推荐 credentials 域,GUI 卡片也可填 serper key):
~/.dsh/.credentials.yaml的refs:下加SERPER_API_KEY: <serper key>与DEEPSEEK_API_KEY: <deepseek key>(后者通常已有);- 或启动环境变量
SERPER_API_KEY/DEEPSEEK_API_KEY。
2. 重启 dsh web。首次启动时,如果用户层没有对 searchProvider 表过态、且当前值仍是部署默认(未设置,或等于部署默认 id;旧构建兜底 deepseek-official),插件会自动把 searchProvider: serper 写进 ~/.dsh/profiles/web/cordis.patch.yml,并在自己的条目里写 takeOverProvider: false(一次性标记)。这两行是预期行为,见[卸载与恢复](#卸载与恢复)。
3. 确认生效:
dsh --profile web --dump-config | grep -A4 "^- id: web$" # 看到 searchProvider: serper 即本插件生效
4. 可选:调插件参数(同一个 patch 文件):
- id: web-search-serper
config:
serperTimeoutMs: 10000 # serper 单路超时;本机实测 1.6–11s,默认 4500 偏紧
cacheMinutes: 0 # 关闭结果缓存(默认 5 分钟)
用户层已经写了别的 provider(例如在 GUI 里开过「启用新版 Web 搜索 API」)时,插件不会抢,只打一行 warn;要切回本插件见 [FAQ](#faq)。
环境变量注意:插件自动写入的searchProvider落在用户 patch 的 config 层,而 DSH 的选路语义是 config 优先、环境变量仅作兜底——所以这条自动 pin 优先于启动环境里的$DSH_WEB_SEARCH_PROVIDER。反过来,如果启动时显式设置了$DSH_WEB_SEARCH_PROVIDER,插件把它当作运维已表态:值为serper时才继续接管(必要时补 pin,否则只写标记);是其它 provider 时只打一行 warn 并写一次性标记,不改你的选路。
卸载与恢复
先明确接管写了什么。首次启动的接管会改 ~/.dsh/profiles/<profile>/cordis.patch.yml 里的两处:
- id: web
config:
searchProvider: serper
fetchProvider: http # ← 一并冻结进用户层(值没变,只是随整个 config 被写入)
- id: web-search-serper
config:
takeOverProvider: false # ← 一次性标记:以后不再自动接管
fetchProvider: http 一起被写进用户层是 configEditor.edit() 写完整 config 的副作用,值没有变化,保留默认即可。因为有 takeOverProvider: false 这个标记,下面三条恢复路径重启后都不会被重新接管:
1. 设置 → 网页搜索,在官方设置页切换 provider(切到 deepseek-official 或 deepseek-search-api);
2. 插件卡片 →「恢复部署默认」:清掉用户层的 searchProvider({op:'unset'}),回到继承值;
3. 手删:删掉 - id: web 里的 searchProvider 行,或整行 - id: web。
想重新用本插件:卡片点「设为本机默认搜索」,或手写 searchProvider: serper(也可以把 takeOverProvider 改回 true 让下次启动重新判定一次)。
卸载/禁用:
- 推荐顺序:先点「恢复部署默认」,再
dsh plugin --profile web remove dsh-serper-search→ 搜索照常走官方; - 直接删插件(pin 还留在 patch 里)→ 启动/搜索报
provider "serper" is not registered。这是已知状态,插件没有卸载钩子、不承诺自愈;删掉searchProvider那行(或整行- id: web)即恢复; - 只禁用条目(bundle 还在、pin 已写)同理;
- 卸载后重装:卸载不会删除用户 patch 里本插件条目的
takeOverProvider: false(一次性标记仍有效),所以重装后不会自动接管;点卡片「设为本机默认搜索」,或删掉该字段后重启,才会重新判定。
老用户注意:0.4.0 之前手动 pin 过serper的 profile,升级后会被识别为「用户已表态」——插件不改你的 pin,只补写takeOverProvider: false。也就是说以后你删掉这行 pin,插件不会再自动接管(这正是 0.4.0 的设计:恢复过的状态不被抢回)。
GUI 设置页
Plugins → dsh-serper-search bundle 详情页是一个表单,按三个搜索源分成三组(同一张表单、同一次「保存」覆盖三组):
组 · 组内开关 · 组内凭据(各自独立的引用与状态徽标) · 组内参数
DeepSeek 搜索(Search API) · native · deepseekApiKeyEnv(默认 DEEPSEEK_API_KEY) · deepseekBaseURL、deepseekCount、summaryMaxChars、deepseekTimeoutMs
serper / Google · serperEnabled · apiKeyEnv(默认 SERPER_API_KEY) · baseURL、gl、hl、num、serperTimeoutMs
元宝搜索(腾讯云 WSA) · yuanbaoEnabled · yuanbaoApiKeyEnv(默认 YUANBAO_API_KEY) · yuanbaoEndpoint、yuanbaoCnt(0=自动)、yuanbaoTimeoutMs
三个凭据框彼此独立:各自按本组的引用名向 credentials 域查询「已配置/未配置」、各自 set 写入、改本组引用只刷新本组状态。开关留空 = 继承上层配置,true/false 显式生效(UI 上每组都有「留空表示继承上层配置」的提示)。所有密钥只走 DSH credentials(SERPER_API_KEY / DEEPSEEK_API_KEY / YUANBAO_API_KEY),卡片与 README 都不放明文 key。
每个凭据框下面还有一条「还没有 API Key?」的官方入口外链(新标签页打开,纯链接、不用配置):
平台 · 入口 · 一句话说明
DeepSeek · <https://platform.deepseek.com/api_keys> · 创建 API Key;充值与用量在费用中心
serper · <https://serper.dev/dashboard> · 注册后在 Dashboard 取 key,含免费额度
元宝(腾讯云 WSA) · <https://console.cloud.tencent.com/wsapi> · 控制台开通「联网搜索 WSA」;可领每月 2000 次免费额度
卡片底部是 0.4.0 新增的运行时面板,四个按钮:
…(truncated)
Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::11,最后更新 2026-10-30