DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

asdshuaishuai /

asdshuaishuai/websearch-plugins

Verified

API-key-free aggregate search (16 domestic+overseas engines with result-layer failure filtering) plus direct target-URL fetch with SSRF protection, as providers for the DeepSeek Harness web seam (ctx.web).

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

websearch-plugins

个人用的 DeepSeek Harness 搜索插件包:聚合搜索(16 个国内+海外引擎,结果层过滤)+ 目标网址直接抓取,全部不依赖任何 API Key。注册后 web_search / web_fetch 工具在 没有 DEEPSEEK_API_KEY 的环境里也能真实可用。

基座思路:PhantomJS 式无头抓取

基座是最上游的 ariya/phantomjs(BSD-3-Clause)的无头抓取 思想——“scriptable headless browser”:不渲染 GUI、不依赖浏览器,直接用代码把网页数据拿给 agent 用。 (本地基座素材来自我的 fork asdshuaishuai/phantomjs, 与上游是同一份源码。)这里把同一哲学在 Node 里落地为 全方面适配 的聚合搜索:不针对某台机器/某个网络, 而是把国内 + 海外的引擎全部配上;谁通谁用,网络异常/被墙/验证码/空结果的引擎直接在结果层过滤。

引擎清单(16 个,全部注册、按需过滤)

区域 引擎(provider id = phantom-<id>)
国内 domestic baidu 百度、sogou 搜狗、so360 360搜索、smcn 神马、bingcn 必应中国
海外 overseas bing 必应国际、google、duckduckgo、brave、mojeek、qwant、ecosia、yahoo、yandex、startpage、searx(SearXNG searx.be)

每个引擎既可单独用(phantom-<id>),也默认全部汇入聚合 phantom-aggregate。

三个 provider

  • phantom-aggregate(web_search 默认选中):16 个引擎并行 fan-out,能通就收, 留在结果层的只有成功项——失败/超时/被墙/空结果的引擎被过滤并把原因写进摘要; 跨引擎按 URL 归一化去重(同一条目优先保留带摘要的),轮询交错排序让 top-N 覆盖多个引擎, 按 maxResults 封顶。
  • phantom-<engine>:16 个单引擎 provider,可单独指定。
  • phantom-http(web_fetch):直接抓取目标网址。手工逐跳处理重定向,每跳做 SSRF 防护(拒绝环回/私网/链路本地/CGNAT/保留地址,域名先解析再校验); 非 2xx 视为结果而非错误;HTML 上限 1MB / 文本 512KB,超出截断并置 truncated。

实现原理

一条搜索请求怎么走

模型调用 web_search(query)
  └─ dsh-tool-web 工具 → ctx.web.search({query, maxResults})     ← harness 的 web 接缝
       └─ seam 按 web.searchProvider 选中 phantom-aggregate
            └─ AggregateSearchProvider.search()
                 ├─ 并行 fan-out:16 个 SerpSearchProvider(各自抓取 + 解析,互不阻塞)
                 │    ├─ 抓取层 = 浏览器式无头请求(见“关键设计”)
                 │    │    ├─ HTTP 主路:Chrome 桌面级完整标头 + cookie jar
                 │    │    └─ JS 壳/反爬页 → 专为本插件常驻的极简无头 Blink 渲染服务(CDP)渲染再解析
                 ├─ Promise.allSettled → 结果层过滤
                 │    ├─ rejected(超时/403/被墙/网络错误)→ 丢弃,计入“已过滤异常”
                 │    └─ fulfilled 但解析为空 → 丢弃,计入“已过滤无结果”
                 ├─ 跨引擎去重(URL 归一化)+ 轮询交错
                 └─ 按 maxResults 封顶 → WebSearchResult{ sources, content(聚合摘要) }

关键设计

  • 能力接缝,不是工具:插件只做 ctx.web.registerSearchProvider({id, available(), search()})。 面向模型的 web_search 名称/描述/schema/呈现全部由 dsh-tool-web 拥有;provider 一行都不肖 写进模型。available() 是廉价本地检查(无网络 IO)。
  • 为什么是“结果层过滤”:聚合的输入是“16 个引擎全上”= 通用适配(不针对本地);输出层把 不通的引擎滤掉 = 结果层过滤。所以这台机器通不了 Google/DDG 也不影响聚合结果,换到出口更宽的 网络它们会自动开始贡献。
  • 浏览器式无头请求层(PhantomJS 的法子):对端网站要看到的是一个真实浏览器——
    • 请求默认带完整 Chrome 桌面级标头(sec-ch-ua/sec-fetch-*/upgrade-insecure-requests/accept-language 等), 而不是裸库 UA;
    • 进程内按域名维护 cookie jar,首次访问种下的 BAIDUID/MUID 之类延续到后续搜索, 像浏览器会话一样;
    • 当返回体是 JS 壳/反爬页(无结果标记却有 captcha/x5sec/are you not a robot 等标记)时, fetchMode: auto 会把 URL 交给一个专为本插件服务的常驻极简无头浏览器:只起一次的 Blink(Chromium) 无头进程,开标签→导航→等 readyState=complete→取 outerHTML→关页, 全程走 CDP(内置 WebSocket,零依赖),跨搜索复用;没有完整浏览器时再回落 --headless=new --dump-dom 一次性渲染。这就是上游 PhantomJS 那句 “scriptable headless browser”。对 IP 层风控(本机把 Shenma/Yandex/Mojeek 判断为自动查询)无头浏览器也过不去, 结果层照样过滤;换到放行的网络/IP 上,这类 JS 壳引擎会自动被常驻渲染器解锁。
    • 每引擎的 Chrome 兜底带负缓存(连续失败 2 次本进程内不再试),避免被风控的引擎每次都白等几秒。
  • 单引擎解析是 best-effort:每个引擎一个轻量正则解析器(提取结果 URL/标题/摘要);某引擎的 专属选择器解析不到时自动回落通用 <h3> 锚点扫描;源头标记质量差(如百度/360 把结果包在 baidu.com/link、so.com/link 跳转里)是引擎自身行为,不是插件缺陷。
  • fetch 的 SSRF 防护:web_fetch 用手工逐跳跟随重定向,每一跳先把域名/字面 IP 解析并校验——环回(127.0.0.0/8, ::1)、私网(10/8, 172.16/12, 192.168/16)、链路本地 (169.254/16, fe80::/10)、CGNAT(100.64/10)、保留/组播地址一律拒绝,才发请求。
  • 错误分类:调用方取消 → WEB_ABORTED;单引擎超时/HTTP 失败 → WEB_PROVIDER_ERROR (聚合层整体捕获并过滤,不打断整次搜索);web_fetch 抓非公网目标 → WEB_PROVIDER_ERROR。
  • 零外部运行时依赖:只用 Node 内建 fetch / node:net / node:dns; @deepseek-ai/dsh-web 的 WebError 通过包内 node_modules -> ~/.dsh/profiles/node_modules 符号链接解析(与 harness 的 shared-module fallback 一致)。

结构

websearch-plugins/
  package.json            # 标准 DSH 插件声明:dsh.bundle.patch / exports / keywords / repository
  cordis.patch.yml        # 插件自带的 bundle 层:注册 + 选中聚合 + 挂 fetch + 打开 web_fetch
  lib/
    index.js              # Cordis 插件:name / inject(['web']) / apply(),注册全部 provider
    net.js                # 共享网络层(浏览器式标头 + cookie jar)+ 文本/URL工具 + SSRF 防护
    engines.js            # 16 个引擎的 URL 构造 + 解析器(失败回落通用 h3 锚点)+ JS 壳判定
    chrome.js             # 一次性无头 Chrome(--headless --dump-dom)渲染后端(兜底)
    headless.js           # 专为本插件的常驻极简无头 Blink 渲染服务(单例进程 + CDP,零依赖)
    search.js             # 单引擎 provider(HTTP/auto/Chrome)+ 聚合 provider
    fetch.js              # web_fetch 的目标网址抓取 provider
    types/index.d.ts
  test/
    engines.mjs           # 引擎连通性巡检矩阵(HTTP/auto/chrome 三档)
    diagnose.mjs          # 失败归因:网络 vs 风控/JS壳 vs 解析空
    aggregate.mjs         # 直接跑聚合 provider
    headless.mjs          # 常驻无头渲染服务:JS 执行 + 渲染 + 复用提速
    plugin.mjs            # 模拟 ctx.web 注册表:聚合搜索 + fetch + SSRF 验证
  README.md LICENSE

接入方式(标准 DSH 插件)

本包是一个标准 DSH 插件:package.json 声明了 dsh.bundle.patch(自带 cordis.patch.yml 层),因此可用 dsh plugin 直接装成 profile bundle,不用手工改 profile 补丁 (注册 provider、选中 phantom-aggregate、挂 phantom-http、打开 web_fetch 全部由插件自带层完成)。

本地安装:

dsh plugin --profile web add file:/home/kelthas/code/websearch/websearch-plugins

从 GitHub 安装(最上游发布源):

dsh plugin --profile web add github:asdshuaishuai/websearch-plugins

dsh plugin 会把它加进 dsh.profile.bundles,之后重启 GUI(在启动 dsh web 的终端里 Ctrl+C 后重新运行)并刷新页面即生效。

旧方式(手动)——仅当不便 dsh plugin 时可选:软链 ~/.dsh/profiles/node_modules/websearch-plugins → 本目录,并手工在 ~/.dsh/profiles/web/cordis.patch.yml 写 insert: [web-search-phantom] + web.searchProvider/fetchProvider + tool-web.fetch 三处。装了标准 bundle 后不要再叠加手工条目, 避免重复 id。

想切回 DeepSeek 官方搜索:把 profile 补丁(或本包 cordis.patch.yml 里的) web.searchProvider 改回 deepseek-official 即可(deepseek provider 从未被删除)。

仓库 topic(供 dshmk 插件市场收录)

本仓库声明了 dsh-plugin(dshmk.com 的 DSH 插件市场正是按此 topic 自动收录 GitHub 项目)以及 deepseek-harness / web-search / headless-browser / phantomjs。

配置

web-search-phantom 行 config: 里全部可选:

config:
  engineCount: 5            # 聚合时每个引擎取的条数(默认 5)
  aggregateMaxResults: 10   # 无 maxResults 时的总条数上限
  engineTimeoutMs: 7000     # 每个引擎的默认超时(毫秒);通不了的引擎按此快速过滤
  include: [baidu, bing, google]   # 只聚合这些引擎(默认全部)
  blockedHosts: [...]              # 额外过滤的域名
  fetchMode: auto           # http(纯浏览器式抓取) | chrome(恒走常驻无头渲染) | auto(HTTP优先,JS壳自动渲染兜底)
  chrome:                   # 常驻无头 Blink 渲染服务参数
    path: ""                # 留空自动探测(优先极简 headless-shell,其次 chrome/chromium)
    timeoutMs: 7000         # 单次渲染超时
    settleMs: 400           # 加载完成后再等 JS 出 markup 的缓冲
    virtualTime: 1500       # 一次性渲染兜底的 virtual-time 预算
    browserTimeoutMs: 12000 # 常驻浏览器启动超时
  engines:                  # 单引擎覆盖(可带 fetchMode)
    bing:    { count: 8, timeoutMs: 5000 }
    baidu:   { count: 5 }
    smcn:    { fetchMode: chrome }   # 例:神马强制无头渲染
  userAgent: "Mozilla/5.0 ..."
  fetch:                    # web_fetch
    timeoutMs: 15000
    maxBytesHtml: 1048576
    maxBytesText: 524288
    maxRedirects: 5

失败归因速查:网络不通(Google/DDG/Brave/Qwant/Yahoo/Startpage/SearXNG 在本机超时) 属出口环境问题,暂不处理;IP 层风控(神马/Yandex 验证码、Mojeek 403)连真无头浏览器都过不去, 结果层自动过滤;换到放行网络它们才会上。解析器对各引擎真模板均可用。

错误与取消

  • 调用方取消 → WebError WEB_ABORTED
  • 单引擎超时/HTTP 失败 → 各自 WEB_PROVIDER_ERROR;聚合层全部捕获并过滤,不抛错
  • web_fetch 抓私网/环回/链路本地目标 → WEB_PROVIDER_ERROR(SSRF 防护)
  • 所有 provider 均 honor AbortSignal;available() 为廉价本地检查(无网络 IO)

致谢

感谢最上游的 PhantomJS 项目 ariya/phantomjs (BSD-3-Clause,已归档):本项目只借用了它“scriptable headless browser / 用脚本直接取网页数据” 的思路,未复制其代码;这里把同一哲学在 Node 中实现为聚合搜索与直接抓取。 同时感谢 DeepSeek Harness 的 web 能力接缝 (@deepseek-ai/dsh-web 定义 ctx.web,dsh-tool-web 承载面向模型的工具;provider 写法参考了 @deepseek-ai/dsh-web-search-deepseek)。本项目代码为原创,LICENSE 采用 MIT。

自检

node test/engines.mjs               # 引擎连通性矩阵(http;传 auto/chrome 可测无头兜底)
node test/diagnose.mjs              # 失败归因:网络不通 vs 风控/JS壳 vs 解析
node test/aggregate.mjs "query"     # 直接跑聚合,看过滤/去重/摘要
node test/headless.mjs              # 常驻无头渲染服务:JS 执行 + 渲染 + 复用提速
node test/plugin.mjs "query"        # 模拟 seam:聚合 + web_fetch + SSRF 防护

继续迭代(维护指南)

  • 加引擎:在 lib/engines.js 的 ENGINES 数组加一个 engine(id, region, label, buildUrl, parse), 解析器 Share 通用 <h3> 回落,无需改别处;聚合/单引擎/过滤自动生效。
  • 调优某引擎:profile 补丁 web-search-phantom.config.engines.<id> 里给 count/timeoutMs/fetchMode, 或全局 fetchMode / chrome / engineTimeoutMs。
  • 改配置形状:动了 index.js 的 DEFAULT_CONFIG 后同步 lib/types/index.d.ts。
  • 回归:跑上面 自检 一节全部脚本再提交。
  • 发布新版本:git tag vX.Y.Z && git push origin vX.Y.Z,再 gh release create vX.Y.Z; 标准 bundle 安装方(dsh plugin add github:...)会拿到新版本。仓库保持 dsh-plugin topic, dshmk 插件市场会自动收录/更新。
—/ 5

No ratings yet

Verified DSH bundle

Commit bd4e553d4f41

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