DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

Wandering233 /

Wandering233/dsh-keyless-search

Verified

免 API key 的多引擎搜索 provider for DeepSeek Harness (ctx.web):真实浏览器 Google + 国际版 Bing + 中文 Bing,带代理自动探测、语言感知与浏览器空闲回收

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@44602d8d

dsh-keyless-search

License: MIT Node Platform API key dsh plugin

免 API key 的多引擎搜索 provider,为 DeepSeek Harness(dsh)的 ctx.web 搜索接缝提供后端。

装上它之后,内置的 web_search 工具照旧可用,但底层不再是"一次搜索 = 一整个模型轮次"的官方服务端搜索,而是由本插件自己发起检索。

特性

  • 不需要任何 API key —— 不依赖 DEEPSEEK_API_KEY,也不消耗模型轮次
  • 真实浏览器 Google —— 用本机 Chrome 渲染 google.com,绕开纯 HTTP 抓取必然撞上的 enablejs JS 墙
  • 三引擎可降级 —— google-browser / bing-global / bing 并发合并,代理不可用时自动收敛为直连
  • 代理自动探测 —— 不填 proxyUrl 也会自动扫本地常见端口,换机器零配置
  • 语言感知 —— 中文查询自动跳过国际版 Bing,避免无关英文结果污染
  • 多主题查询自动拆分 —— 一条查询塞多个主题(如"内存、8TB 硬盘、OCuLink 卡的 2026 年现状")时,自动按分隔符拆成最多 8 个子查询、各主题独立检索后合并去重,避免搜索引擎只匹配主体词而丢掉其余主题
  • 浏览器实例自动回收 —— 空闲(默认 5 分钟)后自动关闭自己拉起的那个 Chrome,不碰你自己的浏览器
  • 零 host 依赖 —— 只用 node: 内置模块,不从 @deepseek-ai/* import 任何东西
  • 不拖垮 dsh —— puppeteer-core 缺失或 Chrome 找不到时只降级单个引擎,绝不影响 dsh 启动

目录

  • 为什么需要它
  • 三个引擎
  • 安装
  • 跨平台
  • 配置
  • 已知限制
  • 开发与自检
  • 故障排查

为什么需要它

dsh 内置的搜索 provider(dsh-web-search-deepseek)依赖 DeepSeek 的服务端 web_search 工具:

  • 需要 DEEPSEEK_API_KEY
  • 每次搜索会消耗一个完整的 Messages 模型轮次(延迟 + 生成 token 都要付)

本插件改为自己发请求,因此不需要任何 API key、不消耗模型轮次。

三个引擎

引擎 id 通道 结果特征 实测
google-browser 真实 Chrome 渲染 google.com,经代理 真实 URL + 带日期的摘要,Google 独有排序(reddit / x.com / huggingface 等) ✅ 可用
bing-global HTTP 经代理访问 www.bing.com 国际版英文结果(此时不会跳转 CN 版) ✅ 可用
bing HTTP 直连 cn.bing.com 中文结果,无代理时的兜底 ✅ 可用

默认引擎链:[google-browser, bing-global, bing]。

Google 为什么要用浏览器

直接 HTTP 抓 Google 是行不通的:无论用 gbv=1、udm=14、现代 UA 还是换代理出口 IP,返回的都是 httpservice/retry/enablejs 的 JS 墙,0 条结果(四种参数组合均实测)。

真实浏览器会执行 JS,于是能拿到结果页。而 Google 的结果链接是加密的 /goto?url=CAES...,插件用 CDP 的 redirectChain 在不加载目标页的前提下解出真实地址(实测 8/8 成功、438ms),并配合请求拦截丢弃无关流量。

语言感知

国际版 Bing 对中文查询的索引质量差——实测搜"上海天气"会混入秘鲁股票,搜"arcprize"会混入 Seattle 时间站。

因此插件在查询包含中日韩字符时自动跳过 bing-global,只保留 google-browser + bing(Google 对中文的相关性排序很好,bing 直连做中文兜底)。显式指定 engine / engines 时不干预。

安装

# 方式一:从 tarball 安装(推荐,依赖会一并装上)
npm pack                                    # 生成 dsh-keyless-search-<version>.tgz
dsh plugin --profile <profile> add ./dsh-keyless-search-1.0.0.tgz

# 方式二:从本地目录安装(开发用,见下方注意事项)
dsh plugin --profile <profile> add <本包绝对路径>

# 方式三:从 git 安装
dsh plugin --profile <profile> add github:Wandering233/dsh-keyless-search

<profile> 换成你实际使用的 profile 名(如 web、desktop)。

安装后重启 dsh 生效。本包声明了 dsh.bundle.patch,dsh plugin add 会自动把它加入 profile 的 bundle 列表并应用 patch,无需手工改 cordis.patch.yml。

两种安装方式的差异(实测)

tarball 安装 本地目录安装
pnpm 行为 解包到 store,并安装其 dependencies(实测 25 个包) 仅建 symlink(link: 语义),不安装 dependencies
import('puppeteer-core') ✅ 能解析(依赖就在旁边) ❌ 解析失败 —— 因为 ESM 基于真实路径,symlink 指向的是源目录
因此本地目录安装时 — 插件改为扫描 $DSH_HOME/profiles/*/node_modules 找 puppeteer-core

也就是说:本地目录安装时,请确保 profile 里已存在 puppeteer-core:

dsh plugin --profile <profile> add puppeteer-core

若两处都找不到,google-browser 引擎会自动降级(其余引擎照常工作),并在错误里提示修复命令,不会影响 dsh 启动。

运行要求

  • Node ≥ 22
  • Chrome / Chromium / Edge:自动探测(跨平台,见下节);其他位置用 chromePath 指定
  • puppeteer-core:见上表;本地目录安装时建议显式装上
  • HTTP 代理:仅 google-browser 引擎需要(能访问 google.com 即可)

本插件刻意不声明任何 @deepseek-ai/* 的 peerDependencies。它不从 host 包 import 任何东西(只用 node: 内置模块),因此不会出现"profile 的 node_modules 解析不到 asar 内依赖"而导致整个 profile 启动失败的问题。

跨平台

插件只用 node: 内置模块,Windows / macOS / Linux 均可运行。浏览器探测顺序:

  1. chromePath 显式指定
  2. 常见安装路径 —— 覆盖 Arch/Debian/Fedora/Snap 等布局(/usr/bin/chromium、/usr/bin/google-chrome-stable、/usr/lib64/chromium-browser/chromium-browser、/snap/bin/chromium…)、macOS 的 .app 路径、Windows 的 Program Files
  3. puppeteer 自带缓存 —— ~/.cache/puppeteer/chrome/<version>/…(macOS 为 ~/Library/Caches/…),适合没装系统浏览器的 Linux
  4. 扫 PATH —— google-chrome / chromium / chromium-browser / brave-browser 等,各平台文件名差异已覆盖

PATH 分隔符(: 与 ;)差异已处理;路径转 URL 用 pathToFileURL,含空格与非 ASCII 的路径也安全。

Linux 注意事项

  • --no-sandbox 与 --disable-dev-shm-usage 已默认启用(root / 容器环境通常必需)
  • 需要 Chromium 运行库:Arch 直接装 chromium 包即可;Debian 系常见缺 libnss3 libatk-bridge2.0-0 libgbm1 libasound2
  • 没装浏览器也不会崩:google-browser 引擎失败后自动降级到 bing,搜索照常可用
  • 代理端口按 Linux 习惯也覆盖了(1080 / 7890 / 7897)—— v2rayN 在 Windows 常用 10808,Clash 常用 7890,proxyUrl 留空时会自动探测

配置

写入 profile 的 cordis.patch.yml 中本插件行的 config:

- insert:
    - id: web-search-local
      name: 'dsh-keyless-search'
      config:
        engines: [google-browser, bing-global, bing]
        proxyUrl: ''            # '' = 自动探测;'off' = 强制直连;或 'http://host:port'
        maxSources: 16
        browserTimeoutMs: 30000
        searchTimeoutMs: 15000
        chromePath: ''          # 留空自动探测
        puppeteerPath: ''       # 留空走包名解析,失败再兜底已知路径
        searxngBaseUrl: ''      # 可选,见下
字段 默认 说明
engines [google-browser, bing-global, bing] 引擎链;其他可选:duckduckgo、searxng
proxyUrl '' 空 = 依次探测 10808 / 10809 / 7890 / 7897 / 1080 / 8888 / 8118 这些本地端口,命中即用
maxSources 16 单次搜索最多返回的来源数
searchTimeoutMs 15000 HTTP 引擎超时
browserTimeoutMs 30000 浏览器引擎超时(含冷启动)
browserIdleTimeoutMs 300000 浏览器实例空闲多久后自动回收(毫秒);0 表示禁用、实例常驻
chromePath 自动 Chrome/Edge 可执行文件
puppeteerPath 自动 显式指定 puppeteer-core 入口文件
proxyProbeTtlMs 60000 代理探测结果的缓存时长
proxyProbeTimeoutMs 1200 单次代理探测超时

代理行为

  • proxyUrl 留空 → 自动探测本地常见端口,找到就并发跑境外引擎,找不到就只跑直连 bing(省时间、省带宽、避免重复结果)
  • 'off' → 强制直连,只用 bing
  • 显式 URL → 只探测该地址

代理只作用于需要它的引擎(google-browser / bing-global / searxng);bing 始终直连——把国内引擎塞进境外出口 IP 反而会触发验证墙。

关于 SearXNG(可选)

searxngBaseUrl 填一个自建 SearXNG 实例即可启用元搜索(它内置 google 引擎)。但请注意实测结论:

  • 公共实例基本不可用:searxng.site 对 JSON 返回 403,searx.be 不返回 JSON(需在实例的 settings.yml 里开启 search.formats 包含 json)
  • Windows 上跑不起来:uwsgi 需要 os.uname()、SearXNG 的 valkeydb.py 直接 import pwd,都是 Unix 专有依赖

所以除非你在 Linux/WSL/Docker 里有实例,否则建议直接用 google-browser。

已知限制

  • 浏览器引擎有冷启动成本:首次搜索要拉起 Chrome(约 3-6s),之后实例复用(约 3-4s)。实例空闲 5 分钟后自动回收(browserIdleTimeoutMs 可调,0 表示常驻),插件卸载时也会关闭。
  • DuckDuckGo 已不可用:实测返回 HTTP 202 + cc=botnet 反爬页(html 与 lite 端点均如此),因此默认不启用。
  • mojeek 实测返回 0 条(选择器失效),未实现。
  • 工具层最多只给模型 8 条结果:即使插件返回更多(实测 10 条),dsh-tool-web 仍会截断到 searchMaxResults 的默认值 8。 注意:这个上限无法通过 profile 的 cordis.patch.yml 调高。 原因(查自 app.asar 内的 patch):dsh-base 挂载的 tool-web 是 host 行,而 dsh-web-app 明确把它 disabled: true,改为在每个 agent preset 里组合这两个工具——preset 在 asar 内、随 dsh 安装只读。想调整需自定义 agent preset($DSH_HOME/.agent-presets),收益有限,故不建议。

开发与自检

包内自带 selftest.mjs,可以直接用纯 Node 跑(插件零 host 依赖,不需要 dsh 运行环境):

node selftest.mjs

它会依次验证:三个引擎各自可用、代理自动探测、语言感知(中英文查询的引擎差异)、无代理降级,并打印每条链的 plan 与耗时。

改完代码后重新打包并升级:

npm pack
dsh plugin --profile <profile> add ./dsh-keyless-search-<version>.tgz

实现要点

文件 说明
index.js 全部实现:HTTP 层、代理 CONNECT 隧道、三个引擎、分层合并、cordis 入口
cordis.patch.yml bundle patch:插入插件行并选中 provider
selftest.mjs 真实网络自检

几个踩过坑的设计:

  • HTTP 层是手写的(基于 node:net / node:tls),刻意不用 https.request:把已建立的代理隧道 socket 交给它会导致二次 TLS 包装,表现为 ECONNREFUSED。
  • Google 的真实 URL 用 CDP redirectChain 解出,并 abort 掉目标页请求——既不渲染目标页,也不浪费流量(实测 8/8 成功、438ms)。
  • Chrome 实例复用 + 空闲回收:避免每次搜索重付启动开销;空闲超过 browserIdleTimeoutMs 后自动关闭。
  • 回收只作用于自己启动的实例:走 puppeteer 的 proc.close()(连带收尾该实例的子进程与临时 profile),失败才退化为对该实例自身进程句柄的 kill()。代码里不存在 taskkill / Stop-Process -Name chrome 这类按进程名批量匹配的写法,因此绝不会碰到你手动打开的浏览器;只要有搜索正在使用该实例,回收就会被推迟。
  • puppeteer-core 三档解析:显式 puppeteerPath → 包名解析 → 扫描 $DSH_HOME/profiles/*/node_modules。

故障排查

现象 原因与处理
web_fetch 报 configured web provider ... is not registered 你的 patch 覆盖了 web 行却漏掉 fetchProvider。整行替换语义下必须重述 fetchProvider: http
搜索报 WEB_PROVIDER_AMBIGUOUS 同时有多个可用 provider 且未指定。在 web 行设 searchProvider: local-multi
所有引擎失败且提到 proxy 代理没起来。检查 proxyUrl/端口,或设 'off' 只走直连
puppeteer-core not loadable 依赖没装上(手工 file:// 加载时常见)。执行 dsh plugin add 让 pnpm 安装,或用 puppeteerPath 指定入口
no Chrome found 用 chromePath 指定 Chrome/Edge 路径
Google 结果为空 代理不可用,或 Google 改版导致 DOM 选择器失效(改版时更新 #rso h3 与 .t2Cxc 相关选择器)

许可

MIT

—/ 5

No ratings yet

Verified DSH bundle

Commit 44602d8d0bfb

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout