DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

ThzxxArt /

ThzxxArt/dsh-search-tools

Verified

为 DeepSeek Harness 提供可插拔的网页搜索与正文抓取:支持 SearXNG 搜索、Readability 正文提取,全部在 Web 设置页完成配置。

★ 1 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHubProject homepage
READMESource: main@7f3c49f8

dsh-search-tools

简体中文 · English

Listed on dsh-plugin.org npm CI license

为 DeepSeek Harness(DSH)提供 adapter-first 的网页搜索与正文抓取。所有配置都在 DSH Web GUI 的 设置 → 搜索工具 完成,不要求用户手改 YAML。

仓库版本:0.1.9(2026-10-24)。 本版为 Local Direct 增加 Brave Search 与 360 Search 两个可选 HTML 引擎,并把执行模型改为每引擎独立 worker:一个慢引擎不会吞掉另一个引擎的成功结果。默认引擎仍是 DuckDuckGo + Bing;解析、去重、RRF 融合、域名多样性和缓存都在本地完成,不需要 SearXNG、API key、Reader、浏览器或第三方聚合服务。查询会直接发往启用的公网搜索引擎,但不会经过 SearXNG/Reader;不执行页面 JavaScript。默认搜索仍是 searxng,稳定 provider id 和工具 schema 不变。详细边界见 Local Direct 搜索配置 与 v0.1.9 发布清单。


目录

  • 它解决什么问题
  • 功能一览
  • 工作原理
  • 环境要求
  • 安装与升级
  • 快速开始
  • 设置页说明
  • 配置参考
    • 配置存放位置
    • SearXNG 搜索配置
    • Local Direct 搜索配置
    • Readability HTTP 抓取配置
    • Wire HTTP 抓取配置
    • Jina Reader 抓取配置
    • web_research 配置
    • 接管配置
  • 模型工具
  • 安全模型
  • 适配器开发
  • 本地开发
  • 发布流程
  • 故障排查
  • 已知限制
  • 许可证与第三方组件

它解决什么问题

DSH 自带 web_search 和 web_fetch,但默认后端不一定适合每个人:有人已经有自己的 SearXNG,有人需要把搜索请求走代理,有人希望抓取结果直接是干净的正文,而不是整页 HTML。

dsh-search-tools 把“搜索/抓取后端”从 DSH 核心中解耦出来:

  • 用户可以在 Web 设置页选择后端、填写实例、测试连接;
  • 插件向 DSH 注册稳定 provider id,切换后端不会改变 DSH 的 web.searchProvider;
  • 新增后端只需要注册 adapter,设置页按 manifest 自动渲染,不需要改页面代码;
  • 额外提供 web_research:一次调用完成“搜索 + 抓取前 N 条正文”,适合需要页面内容而非只拿链接的模型回合。

它不做这些事:不提供公共搜索 API,不绕过目标站点的登录/付费墙,也不替代 DSH 的权限与沙箱模型。渲染能力取决于抓取 adapter:readable-http 不执行页面 JavaScript;可选的 wire-http 在本地做浏览器级 HTTP/TLS 指纹和 PDF 文本提取,但同样不执行页面 JavaScript;可选的 jina-reader 会把公网 URL 交给 Reader 服务做浏览器渲染(自托管时留在本机),三者都不登录、不绕过付费墙、不破解验证码。

界面预览

以下截图使用 demo 数据(https://searxng.example.com,无真实凭据):

搜索工具概览

搜索后端与实例卡

Fetch 正文 reader

Jina Reader 抓取配置

功能一览

能力 说明
稳定的搜索/抓取 provider dsh-search-tools、dsh-search-tools-fetch 永不随后端变化
内置搜索 adapter SearXNG:多实例、顺序/轮询、故障转移、JSON/HTML、GET/POST、Bearer/Basic、代理、缓存、分页、域名过滤
本地直连搜索 adapter(可选) Local Direct:本机直接查询 DuckDuckGo + Bing HTML 首页,可选 Brave Search / 360;本地解析/去重/RRF 融合/域名多样性/缓存;不需要服务、Key、Reader 或浏览器,不执行 JS
内置抓取 adapter Readability HTTP:复用 DSH 安全 HTTP,Readability 提取正文,失败可回退原文
本地强抓取 adapter(可选) Wire HTTP:impit 本地浏览器级 TLS/HTTP2 指纹、逐跳公网出口 pinning、Readability、PDF 文本;不需要 Reader/Key/浏览器/容器,不执行 JS
可选渲染抓取 adapter Jina Reader:浏览器渲染、PDF/Office、CSS 选择器、iframe/Shadow DOM、代理选项;目标必须是公网地址,Reader 可托管或自托管
研究工具 web_research:搜索、按并发抓取前 N 页、按页/总预算截断、返回来源与正文
Web 设置页 概览、搜索、抓取、研究、诊断五个页签;Connection / Search behavior 子页、实例卡、内联测试、正文 reader、预算条、字段级错误、诊断、缓存清理、键盘保存
凭据隔离 搜索 token 写入 DSH credentials,不落 YAML、不进日志、不出现在诊断文本
接管与恢复 可选让内置 web_search / web_fetch 使用本插件;关闭时恢复之前的 provider
外部 adapter 通过 ctx.searchTools 注册新后端;设置页自动渲染 manifest 字段

工作原理

DSH ctx.web
  searchProvider = "dsh-search-tools"         (稳定)
  fetchProvider  = "dsh-search-tools-fetch"   (稳定)
        │
        ▼
  SearchDispatcher / FetchDispatcher
        │ 读取 config.search.adapter / config.fetch.adapter
        ▼
  ctx.searchTools(adapter 注册表)
    ├── searxng         内置搜索 adapter(默认)
    ├── local-direct    内置搜索 adapter(本机直连 DDG + Bing)
    ├── readable-http   内置抓取 adapter(默认,DSH 安全 HTTP)
    ├── wire-http       内置抓取 adapter(可选,本地浏览器级 HTTP + PDF)
    ├── jina-reader     内置抓取 adapter(可选,Reader 渲染)
    └── 未来由独立包注册的 adapter

关键设计:

  1. provider id 稳定,adapter 可换。 加一个后端不会改 web.searchProvider,也不会要求 DSH 重启后重新注册 provider。
  2. 配置按 section 开放。 search.adapters 和 fetch.adapters 是开放字典,adapter 自己拥有默认值与校验逻辑;核心 schema 不需要为每个后端加字段。
  3. manifest 驱动设置页。 Host 路由把 adapter manifest 发给浏览器,页面按 fields 通用渲染。新增 adapter 不需要改 React 代码。
  4. 配置在调用时解析。 Dispatcher 每次按当前配置选择 adapter;切换后不需要重新注册 provider。

架构细节见 docs/architecture.md。

环境要求

项目 要求
DSH >=0.2.1-rc.2 <0.3.0(当前按 0.2.1-rc.2 验证)
Node.js `^22.19.0
搜索后端 Local Direct(不需要部署,直接查 DDG/Bing)或一个可访问的 SearXNG 实例;也可暂时保持 DSH 默认搜索
抓取后端 公网 http(s) 页面;readable-http 由 DSH SSRF 防护拦截内网,wire-http 在本地逐跳 pin 公网地址,jina-reader 在发出前做公网目标守卫
Reader(可选) r.jina.ai 的 API key,或一个可访问的自托管 Jina Reader 端点;不配置时继续用 readable-http 或 wire-http
浏览器 DSH Web GUI(设置页只在 Web 端注册)

DSH 本身仍是 preview 软件,接口可能变化。插件把 peer 范围锁在已验证的 0.2.1-rc.2 线,升级 DSH 前请先看 CHANGELOG。

安装与升级

方式一:Web UI(推荐)

  1. 打开 DSH Web GUI。

  2. 进入 插件(Plugins)。

  3. 点击 添加插件(Add plugin)。

  4. 输入包名:

    dsh-search-tools
    
  5. 安装完成后启用这个 bundle。

  6. 打开 设置 → 搜索工具。

设置页出现,说明 Host 与浏览器两半都已加载。

方式二:CLI

dsh plugin --profile <profile> add dsh-search-tools

<profile> 换成实际 profile 名。安装后启动该 profile:

dsh --profile <profile>

方式三:离线 tarball

从 GitHub Releases 下载最新可用的 dsh-search-tools-<version>.tgz,然后:

dsh plugin --profile <profile> add ./dsh-search-tools-<version>.tgz

发布资产与 npm 产物字节一致,适合内网或无法访问 npm 的环境。

升级

DSH 插件目前不支持自动更新。升级步骤:

  1. 先在 设置 → 搜索工具 → 概览 关闭搜索/抓取接管(如果已开启)。
  2. 在 插件 页卸载旧版本。
  3. 重新添加 dsh-search-tools 或新的 tarball。
  4. 重新启用,检查设置页配置是否保留(配置在 profile 的 YAML patch 中,通常不会因重装丢失)。
  5. 重新测试搜索与抓取。

CLI 对应:

dsh plugin --profile <profile> remove dsh-search-tools
dsh plugin --profile <profile> add dsh-search-tools

不要在接管仍开启时直接卸载。内置 web_search 会指向一个不存在的 provider,直到你重装插件或手动恢复 web.searchProvider。

安装后检查

  • 设置 → 搜索工具 能看到五个页签。
  • 诊断 里能看到版本号、配置文件路径、抓取/研究运行状态和缓存统计。
  • 如果模型工具已启用,会话里应能看到 web_research。
  • 搜索测试通过后,才建议开启搜索接管。

快速开始

1. 准备搜索来源

有两条零代码路径:

  • Local Direct(推荐先试):不需要准备任何服务。它在本机直接请求 DuckDuckGo 和 Bing 的公开 HTML 结果页,解析和融合都在本机完成。可额外启用 Brave Search 或 360;Brave 内部使用 Firefox HTTP 指纹,其他引擎遵循 profile 设置。查询会离开本机发往启用的引擎;首次使用请确认所在网络能访问它们。
  • SearXNG:需要一个可访问的 SearXNG 实例。实例地址是 http(s) 绝对 URL,例如 https://searx.example.com;JSON API 需要 search.formats 包含 json,HTML-only 也可以;有认证时准备 Bearer token 或 username:password;有限流时准备多个实例或代理。插件会自动去掉末尾 /search、query 和 hash,实例 URL 里不能带用户名/密码。

2. 在设置页配置

  1. 打开 设置 → 搜索工具 → 搜索。
  2. 在 后端 选择 Local Direct 或 SearXNG。
  3. Local Direct:勾选 DuckDuckGo / Bing / Brave Search / 360 搜索 中至少一个,按需选市场、安全搜索、结果数;不需要实例或密钥。点 测试搜索引擎 可检查可达性。
  4. SearXNG:点击 添加实例,填写实例地址;备注名可选;按需设置引擎、分类、语言、安全搜索、分页、结果数、超时;需要认证时选择 Bearer / Basic 并保存密钥。
  5. 点击 测试,确认返回结构化来源;Local Direct 还会显示可达引擎。
  6. 点击 保存并应用。

3. 配置抓取(可选)

  1. 打开 抓取 页签。
  2. 先保持 Readability HTTP,用默认值测试一个公网页面,例如 https://example.com。
  3. 如果目标站点是 SPA、PDF/Office,或静态 HTTP 抓不到正文,改选 Jina Reader:
    • 托管服务填 https://r.jina.ai/,在 Jina API key 保存密钥;
    • 自托管填 http://127.0.0.1:3000/(仅 loopback 允许明文 HTTP)或 HTTPS 反代地址;
    • 需要动态内容时把 Fetch engine 设为 browser;需要新鲜内容时打开 Bypass Reader cache。
  4. 保存前看 form 顶部的数据边界 warning;测试 通过后保存并应用。
  5. web_fetch 工具默认 30 秒;把 Reader 超时调到 30 秒以上时,必须同时调高 DSH tool-web.fetchTimeoutMs,否则会先收到 TOOL_TIMEOUT。

4. 开启接管(可选)

在 概览:

  • 接管内置搜索:让 DSH 的 web_search 使用本插件的搜索 provider。开启前会先用当前配置跑一次搜索测试,失败则不会接管。
  • 接管内置抓取:让 DSH 的 web_fetch 使用本插件的抓取 provider。

接管状态会写入 DSH 的 web.searchProvider / web.fetchProvider。关闭时插件会恢复之前记录的 provider(activation.previousSearchProvider / previousFetchProvider)。

如果只想用 web_research,不一定要开启接管。web_research 调用的是当前 DSH 的搜索/抓取 provider;不接管时就使用 DSH 默认后端。

5. 使用模型工具

模型会话中可以直接使用:

  • web_search:DSH 内置工具,接管后走本插件;
  • web_fetch:DSH 内置工具,接管后走本插件;
  • web_research:本插件注册的研究工具,不依赖接管,但会使用当前 provider。

web_research 示例参数:

{
  "query": "DeepSeek Harness release notes",
  "max_results": 8,
  "fetch_top": 3,
  "max_chars": 12000
}

返回内容包含 sources、fetched 和 truncated;会话卡片会显示来源数、成功抓取数、抓取详情和截断标记。

设置页说明

概览(Overview)

  • 当前搜索 provider / 抓取 provider;
  • 接管状态与快捷开关;
  • 搜索后端是否可用、搜索来源数(SearXNG 实例或 Local Direct 引擎)、缓存条数;
  • 快速搜索测试与抓取预览;
  • 没有来源时的引导卡片。

搜索(Search)

  • 卡片式 adapter picker:显示 adapter 描述、capabilities、配置状态;
  • SearXNG 实例编辑器:添加、删除、上移、下移、启用/停用、单实例测试;
  • Local Direct 引擎多选、市场、安全搜索、每站结果数;不需要实例;
  • 测试搜索引擎:使用固定探测词,不写缓存,直接列出可达引擎,无实例也能用;
  • 由 manifest 自动渲染的字段;
  • 内联测试:显示耗时、来源标题/链接/摘要、Search notes(例如单个引擎被限流或解析为空);
  • 校验错误会定位到具体字段,搜索草稿的错误不会阻塞抓取测试。

抓取(Fetch)

  • 抓取 adapter 选择与字段;
  • 输入公网 URL 做一次抓取预览;
  • 选择 wire-http 时显示本地边界 notice、浏览器指纹/超时/PDF 字段;它不需要 Key,也不执行页面 JavaScript;
  • 选择 jina-reader 时显示数据边界 warning、API key 和浏览器/Reader 选项;readable-http 仍保留原有字段;
  • 显示状态码、内容类型、字符数、截断标记和正文预览;
  • 内网地址会被 readable-http 的 SSRF 防护或 jina-reader 的公网目标守卫拒绝,这是预期行为。

研究(Research)

  • 启用/关闭 web_research;
  • 默认结果数、最大抓取条数、默认抓取条数、单页/总字符预算、并发、超时;
  • 模型看到的工具提示 预览:描述、参数名、默认值与范围都来自当前草稿;可一键复制;
  • 关闭 web_research 后,保存后模型将看不到这个工具。

诊断(Diagnostics)

  • 配置文件路径;
  • 搜索后端、抓取后端、研究工具的真实运行状态(fetch.available / research.registered);
  • 缓存条数与命中/未命中统计;
  • 清空缓存;
  • 最近错误(环形缓冲);
  • 复制诊断信息(已脱敏)与清空错误;
  • 当前版本。

键盘与状态

  • Cmd/Ctrl+S:保存并应用当前草稿(仅在配置有效且有未保存更改时)。
  • 页签支持 ← / → / Home / End。
  • 保存状态、测试结果、诊断操作都通过 aria-live 播报。
  • 配置被更高层覆盖时页面只读;配置在别处修改时提示冲突,需重新加载。

配置参考

配置存放位置

配置通过 DSH 原生 settings 服务写入当前 profile 的 YAML patch:

$DSH_HOME/profiles/<profile>/cordis.patch.yml

结构大致如下:

- id: dsh-search-tools
  name: dsh-search-tools
  config:
    search:
      adapter: searxng
      adapters:
        searxng:
          enabled: true
          instances:
            - url: https://searx.example.com
              enabled: true
              label: primary
          engines: []
          categories: [general]
          language: all
          safesearch: 1
          pages: 1
          maxResults: 10
          strategy: ordered
          method: GET
          format: auto
          auth:
            type: none
          requestTimeoutMs: 12000
          deadlineMs: 45000
          retries: 1
          cacheTtlMs: 300000
          cacheMaxEntries: 200
          userAgent: dsh-search-tools/0.1.9 (+https://github.com/ThzxxArt/dsh-search-tools)
          proxy: ""
          includeDomains: []
          excludeDomains: []
        local-direct:
          enabled: true
          engines: [duckduckgo, bing]
          market: auto
          safeSearch: moderate
          maxResults: 10
          maxPerHost: 2
          profile: chrome
          requestTimeoutMs: 8000
          deadlineMs: 15000
          retries: 1
          minIntervalMs: 1000
          cacheTtlMs: 300000
          cacheMaxEntries: 200
          maxResponseBytes: 2000000
          proxy: ""
          includeDomains: []
          excludeDomains: []
    fetch:
      adapter: readable-http
      adapters:
        readable-http:
          enabled: true
          readability: true
          minArticleChars: 200
          maxArticleChars: 200000
          maxResponseBytes: 5000000
          maxBodyChars: 2000000
          timeoutMs: 20000
          maxRedirects: 5
          userAgent: dsh-search-tools/0.1.9 (+https://github.com/ThzxxArt/dsh-search-tools)
          failOpen: true
        wire-http:
          enabled: true
          profile: chrome
          timeoutMs: 25000
          maxRedirects: 5
          locale: ""
          maxResponseBytes: 5000000
          readability: true
          minArticleChars: 200
          maxArticleChars: 200000
          failOpen: true
          pdf: true
          maxPdfPages: 10
          maxBodyChars: 2000000
        jina-reader:
          enabled: true
          endpoint: https://r.jina.ai/
          engine: auto
          responseMode: markdown
          timeoutMs: 25000
          maxResponseBytes: 5000000
          maxBodyChars: 200000
          waitForSelector: ""
          targetSelector: ""
          removeSelector: ""
          includeIframes: false
          includeShadowDom: false
          noCache: false
          respectRobots: true
          retainImages: none
          retainLinks: all
          upstreamProxy: none
          locale: ""
          userAgent: ""
    research:
      enabled: true
      maxResults: 8
      maxFetch: 8
      defaultFetchTop: 3
      maxCharsPerPage: 12000
      maxTotalChars: 40000
      concurrency: 3
      timeoutMs: 120000
    activation:
      previousSearchProvider: ""
      previousFetchProvider: ""

不要手改这个文件来配置插件。 设置页会处理校验、section 级 diff、密钥隔离和冲突检测。手改容易写坏 YAML,也可能被更高层 overlay 覆盖。

密钥不进入 YAML。插件通过 DSH credentials 读取:

凭据引用 用途 格式
SEARXNG_TOKEN Bearer 认证 token 原文
SEARXNG_BASIC_AUTH Basic 认证 username:password
JINA_API_KEY Jina Reader Bearer 认证(可选) token 原文;自托管无认证时留空

设置页的密钥字段是 write-only:只显示“已配置/未配置”和来源,不回显值。测试使用已保存的密钥;未保存的输入不会发送。

SearXNG 搜索配置

字段 默认 范围/取值 说明
enabled true boolean 关闭后该 adapter 不可用
instances [] 列表 实例按顺序尝试;每项有 url、enabled、label
engines [] 逗号分隔 留空使用实例默认引擎;例如 google, bing
categories ["general"] 逗号分隔 留空不发送该参数,使用实例默认;通常 general
language all 字符串 例如 zh-CN、en-US
safesearch 1 0 / 1 / 2 安全搜索等级
timeRange 空 day / week / month / year 时间范围
pages 1 1–3 并发请求的分页数,结果合并去重
maxResults 10 1–20 每次搜索最多返回条数
strategy ordered ordered / round-robin 多实例顺序优先或轮询
method GET GET / POST SearXNG 请求方法
format auto auto / json / html auto 先 JSON 后 HTML
auth.type none none / bearer / basic 认证方式
requestTimeoutMs 12000 1000–120000 单次 HTTP 请求超时
deadlineMs 45000 1000–300000 整次搜索总预算,不能小于单次超时
retries 1 0–5 每个实例的重试次数,只重试可重试错误
cacheTtlMs 300000 0–86400000 搜索结果缓存 TTL;0 关闭
cacheMaxEntries 200 0–10000 缓存最大条数;0 关闭
userAgent 带版本号 非空、无换行 请求 UA
proxy 空 http(s) URL 代理;不能包含用户名/密码
includeDomains [] 域名列表 只保留匹配域名,支持子域名
excludeDomains [] 域名列表 排除匹配域名,支持子域名

行为说明:

  • 多实例故障转移:一个实例失败会尝试下一个;全部失败才报错。
  • 重试与预算:单实例重试受 retries 和 deadlineMs 共同约束;预算耗尽后不再尝试新实例。429/5xx 的 Retry-After(秒或 HTTP 日期)优先于指数退避,且同样不超过剩余 deadline。
  • host 校验:搜索/抓取 dispatcher 在 live 配置、页面草稿、probe 和 preview 前调用 adapter 的 validate();非法数字、枚举、数组或跨字段配置返回 SEARCH_CONFIG_INVALID / FETCH_CONFIG_INVALID,不会静默 clamp。
  • 预览与 probe:Search 测试预览使用当前草稿的 maxResults;搜索 probe 使用 requestTimeoutMs 和配置的 GET / POST 方法。
  • JSON / HTML:auto 先请求 JSON;遇到 403/415/406 或 JSON 解析失败时,同实例再请求一次 HTML。401 仍按认证失败处理,不会误判成格式问题。
  • Search notes:SearXNG 的 unresponsive_engines 会被保留为提示。看到 0 条结果时先看这里,可能是引擎被限流/CAPTCHA,而不是查询真的没有结果。
  • 缓存键:包含查询、实例列表、引擎、分类、语言、安全搜索、时间范围、分页、策略、方法、格式、认证类型、代理、UA 和域名过滤;修改这些会自然失效。凭据轮换不会自动改键,建议清空缓存。
  • 域名过滤:在结果进入 sources 前过滤,支持 example.com 匹配 www.example.com。
  • 分页部分成功:一页失败不会丢弃其他成功页;失败页写入 notes,全部失败才报错。

Local Direct 搜索配置

本地边界: Select Local Direct 后,查询由 Host 进程直接发往启用的固定公开 HTML 端点(默认 html.duckduckgo.com、www.bing.com;可选 search.brave.com、www.so.com);解析、去重、RRF 融合、域名多样性和缓存都在本机完成。不需要 SearXNG、API key、Reader、浏览器、Docker 或第三方聚合服务。查询会离开本机;它不执行页面 JavaScript,不登录、不绕过付费墙或验证码。引擎 HTML 结构变化可能导致解析为空,此时会显式报错或写入 notes,不会静默 fallback 到 SearXNG。

字段 默认 范围/取值 说明
enabled true boolean 关闭后该 adapter 不可用
engines ["duckduckgo","bing"] duckduckgo / bing / brave / so360,至少一个 启用的公开 HTML 引擎;结果在本地融合。Brave 由 Firefox HTTP 指纹请求;360 面向中文市场
market auto auto / us-en / cn-zh / gb-en / jp-ja / de-de / fr-fr 传给 DDG kl 和 Bing setlang/cc 的市场
safeSearch moderate off / moderate / strict 映射到 DDG kp、Bing adlt 和 Brave safeSearch
maxResults 10 1–20 融合后返回条数上限
maxPerHost 2 1–5 同一 hostname 最多保留条数,避免单站刷满
profile chrome chrome / firefox Impit TLS/HTTP2 指纹;不是浏览器
requestTimeoutMs 8000 1000–30000 单个引擎请求超时
deadlineMs 15000 1000–60000 整次搜索总预算,不能小于单次超时
retries 1 0–2 失败引擎的重试轮数
minIntervalMs 1000 0–10000 每个引擎的最小请求间隔,避免并发搜索打爆引擎
cacheTtlMs 300000 0–86400000 完整成功结果的缓存 TTL;0 关闭
cacheMaxEntries 200 0–1000 缓存条数
maxResponseBytes 2000000 65536–10485760 单引擎 HTML 上限;超限该引擎失败
proxy 空 http(s) URL 可选代理;不能包含用户名/密码
includeDomains [] 域名列表 只保留匹配域名,支持子域名
excludeDomains [] 域名列表 排除匹配域名,支持子域名

行为与失败语义:

  • 固定 origin,无用户可控 URL。 引擎 URL 由代码构造,只有查询、市场、安全搜索等参数变化;配置里没有自定义 endpoint。测试固定 origin,防止把 adapter 变成开放代理。
  • 不跟随重定向。 Impit 使用 followRedirects:false + redirect:'manual';3xx 视为该引擎失败,不会跟随到未知 host。
  • 无 Cookie / Authorization / JS。 每次搜索新建一个 Impit worker;不发送登录态,不执行页面脚本;worker 在成功、失败、abort、deadline 后都会终止。
  • 本地 RRF。 每个引擎按排名贡献 1/(60+rank+1);同 URL 合并更长标题/摘要;再按 hostname 多样性截断。查询词不参与第二阶段 LLM 重排。
  • 部分成功。 一个引擎失败时返回另一个引擎的结果,并在 notes 写明失败引擎与原因;全部失败抛 LOCAL_DIRECT_ALL_FAILED,不会自动 fallback 到 SearXNG/Jina。若 200 页面的结果全部被 includeDomains/excludeDomains 过滤掉,该引擎仍算成功(空结果 + note),不会误报全部失败。
  • 缓存只写完整成功。 只有所有启用引擎都成功、没有失败 note、且至少有结果时才写缓存;部分成功/空结果不缓存,下一次会重试失败引擎。
  • 探测。 Search 页的 测试搜索引擎 使用固定查询 dsh-search-tools probe,不写缓存;返回可达引擎列表。
  • 不解析广告。 DDG 的 result--ad 和 Bing 的 li.b_ad(即使同时带 b_algo)广告项会被丢弃;DDG uddg 和 Bing ck/a?u=a1... 的跳转链接在本地解包为真实结果 URL。
  • 引擎可用性不是 SLA。 每个引擎都可能限流、返回 202/403 或改版;这是公开 HTML 路径的固有风险。出现空结果时先看 notes 和 测试搜索引擎,必要时切回 SearXNG。

Readability HTTP 抓取配置

字段 默认 范围 说明
enabled true boolean 关闭后该抓取 adapter 不可用
readability true boolean 是否用 Readability 提取正文
minArticleChars 200 0–100000 低于此长度不视为文章正文
maxArticleChars 200000 1000–5000000 提取后正文的文本最大字符数,不是 HTML 长度;不能小于 minArticleChars,也不能大于 maxBodyChars
maxResponseBytes 5000000 1024–50000000 响应体最大字节数
maxBodyChars 2000000 1024–20000000 解码后最大字符数,不能小于正文下限
timeoutMs 20000 1000–120000 抓取超时
maxRedirects 5 0–10 最大重定向次数
userAgent 带版本号 非空、无换行 请求 UA
failOpen true boolean 正文提取失败时回退到原始内容

readable-http 的行为:

  • 复用 DSH 的安全 HTTP provider,目标是阻止 SSRF 和访问内网地址;
  • 只处理 http(s) URL;
  • 只解析文本/HTML;PDF、图片、二进制不会变成正文;
  • 不执行 JavaScript,因此纯前端渲染页面可能抓不到实际内容;
  • maxArticleChars 限制的是提取后的正文文本,不是原始 HTML;truncated 由提取器返回,短正文配长 HTML 不会再误报;
  • 需要截断 HTML 时按块级节点处理;无法安全截断时退回纯文本,保证不会返回半截标签;
  • Readability 失败且 failOpen=true 时返回原始文本/HTML,而不是让整个抓取失败;
  • readable-http 的 /probe 会真实发起一次抓取并返回 HTTP 状态/内容类型。

Wire HTTP 抓取配置

本地边界: wire-http 在本地通过 loopback 出口守卫抓取,不把目标 URL 发给第三方 Reader,也不需要 API key、浏览器、Docker 或系统库。它使用 impit 的 Chrome/Firefox TLS/HTTP2 指纹;不执行页面 JavaScript,所以 SPA 仍应使用 jina-reader。它不会登录、绕过付费墙或破解验证码。

字段 默认 范围/取值 说明
enabled true boolean 关闭后该 adapter 不可用
profile chrome chrome / firefox 浏览器 TLS/HTTP2 指纹;不是浏览器引擎
timeoutMs 25000 1000–180000 worker 与出口守卫的硬超时;默认低于 DSH web_fetch 的 30 秒工具超时
maxRedirects 5 0–10 每一跳重定向都重新经过公网出口守卫
locale 空 BCP 47 可选 Accept-Language,例如 zh-CN
maxResponseBytes 5000000 1024–50000000 原始响应字节上限;超限显式失败
readability true boolean 用 Readability 提取 HTML 正文;关闭时返回原始 HTML
minArticleChars 200 0–100000 正文最小字符数
maxArticleChars 200000 1000–5000000 提取后正文文本上限;不能小于下限,也不能大于 maxBodyChars
failOpen true boolean 提取失败时回退原始 HTML;关闭时返回 WIRE_UNREADABLE
pdf true boolean 本地 PDF 文本提取
maxPdfPages 10 1–20 只读前 N 页;超过上限标记 truncated
maxBodyChars 2000000 1024–20000000 解码后字符上限,HTML/文本/PDF 共用

行为与失败语义:

  • 初始目标先解析并校验,随后每一跳由本地出口代理重新解析;任何 DNS 答案包含私网/loopback/link-local/CGNAT/ULA/IPv4-mapped/6to4/Teredo/已知 NAT64 前缀(64:ff9b::/96、64:ff9b:1::/48)都会被拒绝;网络专用 NAT64 前缀无法在通用运行时中穷举,仍被文档标为残余边界;
  • 只允许 http(s)、80/443,不允许 URL 凭据;代理连接到已验证的 IP,不会再次解析主机名;
  • impit 运行在单次请求 worker 中,成功、失败、取消或超时都会终止 worker;原生 client 不会跨请求残留;
  • 响应按 Content-Type/magic 分流:PDF → 本地 PDF.js 文本;HTML → Readability;文本/JSON → 直接文本;二进制 → WIRE_UNSUPPORTED_CONTENT;
  • 2xx 空 body 返回 WIRE_EMPTY_BODY;4xx/5xx 的空 body 保留状态码;PDF 无文本层返回 WIRE_PDF_UNREADABLE,损坏 PDF 返回 WIRE_PDF_INVALID;
  • 不自动 fallback 到 Jina 或 readable-http,避免把被本地守卫拒绝的 URL 静默发给第三方;
  • 不需要 JINA_API_KEY;设置页不显示 secret 字段。

Jina Reader 抓取配置

数据边界: jina-reader 不是 readable-http 的替代默认值。托管 https://r.jina.ai/ 时,目标 URL 会发给 Jina;只有自托管 Reader 才把页面留在本机。Reader 可能缓存页面,需要新鲜内容时打开 noCache。它不会登录、绕过付费墙或破解验证码。

字段 默认 范围/取值 说明
enabled true boolean 关闭后该 adapter 不可用
endpoint https://r.jina.ai/ http(s) URL 托管服务或自托管 Reader;远程必须 HTTPS,http 仅允许 loopback
engine auto auto / browser / curl browser 强制无头浏览器;curl 使用轻量 HTTP,适合静态页
responseMode markdown markdown / html / text html 会映射为 body.kind=html,交给本地 Readability
timeoutMs 25000 2000–180000 本地硬超时;发给 Reader 的 X-Timeout 会少 1 秒作为等待预算,最小值 2000 保证它仍短于本地截止。超过 30000 还需调高 DSH tool-web.fetchTimeoutMs
maxResponseBytes 5000000 1024–50000000 Reader 返回的 JSON 包体上限;超限返回 JINA_RESPONSE_TOO_LARGE
maxBodyChars 200000 1024–20000000 按响应模式截断 data.content / data.html / data.text,并置 truncated=true
waitForSelector 空 CSS 选择器 等元素出现后再提取
targetSelector 空 CSS 选择器 只提取匹配内容
removeSelector 空 CSS 选择器 提取前移除导航/广告等
includeIframes false boolean X-With-Iframe: true
includeShadowDom false boolean X-With-Shadow-Dom: true
noCache false boolean X-No-Cache: true,要求实时抓取
respectRobots true boolean X-Robots-Txt: dsh-search-tools
retainImages none none / all 默认移除图片,省 token
retainLinks all none / all 是否保留链接
upstreamProxy none none / auto auto 需要 Reader 支持且通常需要 API key
locale 空 BCP 47 例如 zh-CN;控制 Reader 浏览器 locale
userAgent 空 字符串 作为 X-User-Agent 发给目标页;空则 Reader 默认

行为与错误:

  • 请求固定为 POST <endpoint>/,Content-Type: application/x-www-form-urlencoded,body 为 url=<目标>;Accept: application/json,并带 X-Respond-With、X-Timeout 等头。Markdown 请求 markdown;HTML/text 请求 <mode>,content,因为 Jina 把目标站错误warning 放在 content 分支。
  • 目标 URL 在发出前经过公网目标守卫:只允许 http(s)、禁止 URL 内凭据、拒绝 loopback/私有/链路本地地址及 IPv4-compatible 等过渡地址,并要求 DNS 解析结果全部为公网地址。错误码为 JINA_INVALID_TARGET / JINA_TARGET_BLOCKED / JINA_TARGET_UNRESOLVED。
  • 401/403 → JINA_AUTH;429 → JINA_RATE_LIMIT(有 Retry-After 时带 retryAfterMs,最多 1 小时);5xx/其他 → JINA_HTTP;网络失败 → JINA_NETWORK;超时 → JINA_TIMEOUT;非法 JSON/缺少当前模式的字段(data.content、data.html 或 data.text)→ JINA_BAD_RESPONSE(若目标状态已是非 2xx,则返回空正文并保留状态码);超限 → JINA_RESPONSE_TOO_LARGE。
  • Reader 返回的目标页 404/5xx 优先从 data.warning 恢复,其次读官方 data.httpStatus;HTML/text 不再附加 content companion,直接依赖这两个官方字段。可选的 data.statusCode 作为自托管兼容字段最后兜底,且 warning/httpStatus 优先;只有三者都缺失时才无法恢复目标状态。
  • 残余风险: Reader 服务端会重新解析目标 DNS,并可能跟随目标页重定向/浏览器跳转;本插件无法像 HttpFetchProvider 那样 pin 住连接,所以这是 best-effort 守卫,不是 DSH 级别的 SSRF 保证。自托管时请限制 Reader 容器的网络出口。
  • HTML 模式的 maxBodyChars 截断优先落在完整标签边界,但仍可能留下不完整文档;需要 token 预算时优先用 Markdown/text。
  • 自托管: Jina Reader 开源版可运行在本机/内网;把 endpoint 设为 http://127.0.0.1:3000/(或 HTTPS 反代)。托管 Jina 的 API key 只发给你配置的 endpoint,并保存在 DSH credentials。

web_research 配置

字段 默认 范围 说明
enabled true boolean 关闭后模型看不到该工具
maxResults 8 1–20 返回来源数上限,也是 max_results 的上界
maxFetch 8 1–10 抓取页数上限,也是 fetch_top 的上界
defaultFetchTop 3 0–10 模型未指定 fetch_top 时的默认抓取数;不能大于 maxFetch
maxCharsPerPage 12000 1000–200000 单页字符上限,也是 max_chars 的上界
maxTotalChars 40000 1000–500000 所有页面合计字符预算;不能小于单页上限
concurrency 3 1–8 并发抓取数
timeoutMs 120000 5000–600000 工具超时预算

web_research 会把模型参数夹到这些边界内,并按 maxTotalChars 在多个页面之间分配剩余预算。defaultFetchTop > maxFetch 或 maxCharsPerPage > maxTotalChars 会在执行前返回 RESEARCH_CONFIG_INVALID。某个页面抓取失败不会让整次调用失败;失败页会带 error 字段,卡片仍会显示来源和成功抓取数。

超时字段说明: timeoutMs 同时进入工具注册的声明超时和 runResearch 的内部 signal;到点后搜索/抓取会被取消并返回 WEB_RESEARCH_TIMEOUT,不再只是提示词里的展示值。

接管配置

接管不是必选项。

配置 作用
web.searchProvider = dsh-search-tools 内置 web_search 使用本插件搜索 provider
web.fetchProvider = dsh-search-tools-fetch 内置 web_fetch 使用本插件抓取 provider
activation.previousSearchProvider 开启接管前记录的搜索 provider,关闭时恢复
activation.previousFetchProvider 开启接管前记录的抓取 provider,关闭时恢复

规则:

  • 开启搜索接管前,页面会先用已保存配置跑一次搜索测试;失败则不接管。
  • 抓取接管的开关不强制先测试;建议先在 抓取 页手动测试一个公网页面。
  • 关闭接管时,如果之前没有记录 provider,会 unset 对应配置,回到 DSH 默认。
  • 停用/卸载 bundle 前先关闭接管;插件在插件详情页会显示接管警告和“关闭接管”入口。

模型工具

内置 web_search / web_fetch

这两个是 DSH 自带工具。插件不重新发明它们,只通过稳定 provider 接管底层实现:

  • 不开接管:它们继续用 DSH 原来的 provider,本插件不影响;
  • 开接管:请求进入本插件的 Dispatcher,再路由到当前 adapter;
  • 关闭接管:恢复开启前记录的 provider。

这样模型看到的工具名、参数和权限模型都不变。

web_research

插件注册的模型工具,用于“我要页面内容,而不只是链接”的场景。

参数:

参数 类型 必填 说明
query string 是 搜索查询
max_results number 否 返回来源数,受配置 maxResults 限制
fetch_top number 否 抓取前 N 条;0 表示只返回来源
max_chars number 否 单页字符预算,受配置 maxCharsPerPage 限制

返回结构:

{
  "query": "example",
  "sources": [
    { "url": "https://example.com", "title": "Example", "snippet": "..." }
  ],
  "fetched": [
    {
      "url": "https://example.com",
      "title": "Example",
      "content": " readable markdown ...",
      "truncated": false
    }
  ],
  "truncated": false
}

行为:

  • 搜索走当前 ctx.web.search;抓取走当前 ctx.web.fetch;
  • 抓取前 fetch_top 条结果,按 concurrency 并发;
  • HTML 页面会尝试 Readability 提取,再转 Markdown;纯文本直接使用;
  • 单页按 max_chars 截断,多页共享 maxTotalChars 预算;
  • 单页失败带 error,不影响其他页;
  • 会话卡片显示来源、成功抓取数、失败数、字符数和截断标记;
  • 外部页面内容是不可信数据,不是指令。模型和用户都不应执行页面里的“指令”。

安全模型

  • 设置路由有认证栅栏。 所有 /api/dsh-search-tools/* 路由都经过 DSH 的 connection.requestRejection,未认证请求返回 401/403。
  • 请求体有上限。 JSON body 限制 64 KiB,非 JSON 返回 415。
  • SSRF 边界按 adapter 区分。 readable-http 复用 DSH 的 HttpFetchProvider,内网/保留地址会被拒绝;wire-http 在本地 loopback 出口代理中对每个 CONNECT/HTTP 目标和每一跳重定向重新解析 DNS,要求所有答案都是公网,并连接到已验证的 IP(连接级 pinning);jina-reader 在发出前做公网目标守卫,但 Reader 服务端会重新解析 DNS,并且可能跟随目标页重定向/浏览器跳转,因此不能提供与 DSH 相同的连接级 pinning。托管 Jina 时目标 URL 会离开本机;自托管时页面留在 Reader 服务内,但仍应限制 Reader 容器的网络出口。
  • Wire HTTP 不执行页面 JavaScript。 它模仿浏览器 TLS/HTTP2 协议指纹,不是浏览器;SPA 请用 jina-reader。PDF 只在本地用 PDF.js 提取文本,isEvalSupported: false,不执行 PDF 内嵌脚本。
  • Wire HTTP worker 没有持久凭据。 不发送 Cookie、Authorization 或登录态;不登录、不绕过付费墙、不破解验证码。
  • Reader 不是匿名代理。 托管 Reader 可能缓存页面,noCache 只要求实时抓取;自托管也不能绕过登录、付费墙或验证码。
  • 搜索重定向不跟随。 SearXNG 请求使用 redirect: 'error',认证头不会跟随跨源重定向。Local Direct 使用 followRedirects:false + redirect:'manual',3xx 直接视为该引擎失败。
  • 搜索出口按 adapter 区分。 searxng 把查询发给用户配置的实例(可私有/loopback);local-direct 只把查询发给启用的固定公网 origin(默认 DuckDuckGo/Bing,可选 Brave/360),没有用户可控 endpoint,不发送 Cookie/Authorization,也不执行 JS。web_research 的抓取阶段仍只接受公网页面;搜索结果中的本地/私有 URL 不会被 fetch adapter 读取。
  • 凭据不落 YAML。 Bearer/Basic/Jina API key 写入 DSH credentials;YAML 只保存非敏感配置。诊断文本会脱敏,不包含 token。
  • 代理不带凭据。 proxy 必须是 http(s) URL,且不能包含用户名/密码,避免把代理凭据写进配置。
  • 错误信息有限。 实例/目标主机名可能出现在诊断中,但查询字符串和凭据会被去掉。
  • 无遥测。 插件不向作者发送使用数据;SearXNG 搜索请求只发往你配置的实例,Local Direct 请求只发往启用的固定公网引擎,jina-reader 请求只发往你配置的 Reader endpoint(托管 Jina 时该 endpoint 是第三方)。Local Direct 的查询文本会到这些引擎,不会发给本站或其他聚合服务。

安全边界仍然取决于 DSH 本身和你的部署。不要把设置页暴露在不可信网络;不要在共享 profile 中把密钥当公共配置。

适配器开发

外部 adapter contract 在 0.1.x 标记为实验性。接口可能在小版本中调整;依赖它时请锁定 dsh-search-tools 版本并做集成测试。

一个 adapter 包大致做三件事:

  1. 依赖 ctx.searchTools 服务;
  2. 提供 manifest(设置页渲染用)和 runtime(实际搜索/抓取);
  3. 用 ctx.effect 注册,确保卸载时自动清理。
import type { Context } from '@deepseek-ai/cordis'

export const inject = ['searchTools']

export function apply(ctx: Context): void {
  ctx.effect(
    () => ctx.searchTools.registerSearchAdapter(myAdapter),
    'my-search-adapter',
  )
}

myAdapter 的结构:

const myAdapter = {
  manifest: {
    kind: 'search',
    id: 'my-search',
    label: { en: 'My Search', zh: '我的搜索' },
    description: { en: '...', zh: '...' },
    defaults: { endpoint: 'https://search.example.com' },
    capabilities: ['json', 'probe'],
    groups: [
      { id: 'connection', label: { en: 'Connection', zh: '连接' } },
      { id: 'advanced', label: { en: 'Advanced', zh: '高级' }, advanced: true },
    ],
    fields: [
      { kind: 'text', key: 'endpoint', label: { en: 'Endpoint', zh: '地址' }, group: 'connection' },
      { kind: 'number', key: 'timeoutMs', label: { en: 'Timeout', zh: '超时' }, group: 'advanced', unit: 'ms' },
    ],
  },
  validate(rawConfig) {
    return { ok: true, issues: [] }
  },
  create(ctx, getConfig) {
    return {
      available: () => true,
      async search(request, signal) {
        return { sources: [], truncated: false }
      },
    }
  },
}

约定:

  • 搜索 adapter 的 id 必须唯一;kind 必须是 search 或 fetch。
  • 配置存在 config.search.adapters.<id>(或 fetch.adapters.<id>),adapter 自己 normalize/validate。
  • fields 支持 text、url、password、number、boolean、select、tags、checkboxes、instances;可选 group、advanced、unit 只影响展示,不改变配置结构。checkboxes 声明固定 options,用 default 给出多选默认值。
  • groups 可选;不声明时页面渲染单个 Configuration 分组。字段的 group 不存在时回退到第一个分组,advanced: true 的字段自动进入折叠区。
  • 需要密钥时用 secretRefs 声明引用,值走 DSH credentials,不要写进 manifest defaults;secret 也可声明 group / advanced。
  • 新增 adapter 不需要改设置页代码;页面按 manifest 渲染,声明 groups 后自动获得分组与折叠。
  • v0.1.x 不支持 adapter 自带完全自定义的设置 UI;如有需要,可以未来注册自己的 settings.section,但那就不再是统一页面的一部分。
  • 外部 adapter 的本地化目前以 manifest 的 label / description 原文为准;内置 adapter 由插件字典提供中英文。

ctx.effect 返回 disposer;不要在 apply 外保存全局注册状态。重复注册同一 id 会被拒绝。

本地开发

pnpm install --frozen-lockfile --registry=https://registry.npmjs.org
pnpm typecheck
pnpm test
pnpm build
pnpm release

pnpm build 产出:

lib/index.js        Host 半侧
lib/wire-worker.js  wire-http 单次请求 worker
lib/client.js       浏览器 lazy-CJS factory
lib/types/**        TypeScript 声明

测试与检查:

命令 内容
pnpm typecheck TypeScript 类型检查
pnpm test Vitest:Host 单测、设置页/研究卡片组件测试、pipeline、publint 策略
pnpm coverage 同上 + V8 覆盖率门禁;statements / branches / functions / lines 均不得低于 85%
pnpm build Host、浏览器、类型声明
pnpm pack:check build + pnpm pack --dry-run + publint
pnpm release typecheck + coverage + pack:check

CI 在 Ubuntu/Windows × Node 22/24 上跑 typecheck、coverage、build、pack dry-run、publint。publint 只忽略 lib/client.js 的 FILE_INVALID_FORMAT:DSH 把它当浏览器 CJS 工厂加载,不是 Node ESM 入口;其他诊断仍然失败。

项目结构

src/core/                 adapter 类型、注册表、稳定 dispatcher、诊断
src/search/adapters/      SearXNG + Local Direct adapter(manifest/schema/parser/fusion/worker)
src/fetch/adapters/       Readability HTTP / Wire HTTP / Jina Reader adapters
src/research/             web_research pipeline、prompt、render、tool
src/host/                 认证的设置路由
src/client/               设置 → 搜索工具 + 研究卡片
src/shared/               config、校验、diff、URL、公网目标守卫、限制
tests/                    Host 单测 + 设置页/研究卡片组件测试
docs/                     架构、设计、M0 验收、发布清单

为什么用 linkedom 而不是 jsdom

Readability 运行在 Host 内。jsdom 的 tr46 依赖会调用 createRequire(...).resolve.paths,而 DSH 的 profile resolution hook 没有实现它;linkedom 更小,也能在 Host 内工作。jsdom 只作为组件测试的 dev 依赖。

发布流程

发布前确认:

  • package.json 版本是 0.1.9;
  • CHANGELOG.md 有对应条目;
  • pnpm release 全绿;
  • 工作区干净;
  • npm 认证可用,或仓库配置了 NPM_TOKEN secret。

本地检查:

pnpm install --frozen-lockfile --registry=https://registry.npmjs.org
pnpm release
pnpm pack --pack-destination dist

打 tag 并推送:

git tag -a v0.1.9 -m "dsh-search-tools v0.1.9"
git push origin main --follow-tags

推送 v* tag 会触发 .github/workflows/release.yml:

  1. 在 Ubuntu/Windows × Node 22/24 上先跑完整验证矩阵(含 check:package);
  2. 校验 tag 名与 package.json 版本一致,且 tag commit 在 main 上;
  3. 重复 pnpm release;
  4. 检查该版本是否已发布,已存在则跳过;
  5. 用 NPM_TOKEN 发布到 npm(provenance);
  6. 把 tarball 附加到 GitHub Release,并使用 docs/release-v<version>.md 作为发布说明。

手动发布(不产生 provenance;正式发布走 tag workflow):

npm publish --access public

发布后做一次全新 profile 冒烟:安装、启用、分别用 local-direct 和 searxng 做搜索测试、分别用 readable-http、wire-http 和 jina-reader 做抓取测试、一次 web_research 调用。详细清单见 v0.1.9 发布清单。

故障排查

现象 可能原因 处理
设置页没有“搜索工具” bundle 未启用;DSH 版本不匹配;客户端加载失败 在插件页启用;确认 DSH 在 >=0.2.1-rc.2 <0.3.0;看浏览器控制台/插件日志
搜索测试 401/403 实例需要认证;凭据未保存;Basic 格式不是 username:password 在认证字段选择正确类型,保存密钥后重试;确认 Source: env 是否符合预期
搜索测试 429 实例/引擎限流 降低频率、换实例或引擎、增加缓存 TTL,或改用其他后端
Local Direct 全部失败 网络无法访问引擎;引擎返回 202/403/429;解析为空 点 测试搜索引擎 看可达性;换网络/代理;稍后重试;必要时切回 SearXNG
Local Direct 结果偏少 只启用了单引擎;每站上限;引擎只返回首页 多启用一个引擎;提高 maxPerHost/maxResults;看 Search notes
返回 0 条但测试“成功” SearXNG 默认引擎被限流/CAPTCHA 看 Search notes;指定 engines(例如 bing)或换实例
JSON 解析失败 实例未启用 JSON 格式 在 SearXNG 的 search.formats 加 json;或把格式设为 html
web_research is disabled 研究工具关闭 设置 → 研究 → 启用 web_research 并保存
研究只返回来源、不抓正文 fetch_top=0;抓取失败;目标页面不可读 提高 fetch_top;看抓取详情的 error;手动在抓取页测试 URL
内网 URL 抓取失败 readable-http 的 DSH SSRF 防护;jina-reader 的公网目标守卫 预期行为;不要尝试绕过
Jina 抓取返回 401/403 API key 未配置/无效;匿名 IP 被限流 在设置页保存 JINA_API_KEY;或改用自托管 Reader
Jina 抓取返回 429 Reader 限流 稍后重试、降低频率、配置 key/配额,或改回 readable-http
Jina 超时 Reader 浏览器渲染慢;DSH web_fetch 30 秒工具超时先到 降低 timeoutMs 到 25 秒内,或调高 DSH tool-web.fetchTimeoutMs
接管后内置搜索报错 bundle 被停用/卸载但接管仍指向插件 重新启用插件,或关闭接管;设置页/插件详情页有恢复入口
配置保存冲突 配置在别处被修改;更高层覆盖 点 重新加载;检查 profile 的 cordis.patch.yml 和更高层 overlay
配置只读 被更高层配置覆盖 页面顶部会说明;到覆盖层修改,或移除覆盖
实例 URL 重复 规范化后相同 去掉重复实例;URL 会去掉末尾 /search、query、hash
代理配置报错 不是 http(s),或包含用户名/密码 改成无凭据的 http(s)://host:port
缓存结果不更新 TTL 未到 在诊断页清空缓存,或等 TTL 过期
安装后没有 web_research 研究工具关闭;模型未刷新工具列表 启用并保存;开新会话或重新加载页面
npm 安装失败 registry/网络/peer 不匹配 检查 DSH 版本、Node 版本、npm registry;用 tarball 离线安装

诊断顺序建议:

  1. 看 设置 → 诊断 → 最近错误;
  2. 看 Search notes(引擎级错误);
  3. 用 测试 复现,不要只看模型回合;
  4. 确认是否开启了接管,以及当前 provider 是哪一个;
  5. 最后再查 DSH 日志和实例日志。

已知限制

  • 内置两个搜索 adapter 和三个抓取 adapter。 搜索默认仍是 searxng;local-direct 是零部署的本地直连后端,默认查询 DuckDuckGo/Bing,并可选用 Brave Search / 360 公开 HTML,不执行 JS,也不保证引擎永不改版/限流。抓取默认 readable-http;wire-http 是本地浏览器级 HTTP + PDF 后端;jina-reader 是可选 Reader 后端。0.1.x 不附带 Google/Exa 等需要 API key 的商业搜索后端;Brave/360 走公开 HTML 页面,不需要 API key。
  • 没有自动更新。 升级需要卸载再安装。
  • 外部 adapter contract 是实验性的。 0.1.x 可能调整;生产集成请锁版本。
  • 浏览器渲染只属于 jina-reader。 readable-http 和 wire-http 都不执行 JS;wire-http 强化的是 TLS/HTTP2 指纹、出口 pinning 和 PDF,不是浏览器引擎。Jina 需要公网 Reader(托管或自托管),且不处理登录态、付费墙或验证码。SPA 能渲染不等于能登录。
  • readable-http 只处理文本/HTML。 PDF、图片、音视频不会转成正文;wire-http 可本地提取 PDF 文本;需要 Office/浏览器渲染时用 jina-reader。Jina 的 PDF/Office 转换取决于 Reader 服务能力。
  • web_research 不是爬虫。 只抓前 N 条结果,不做站点遍历、去重图谱或深度抓取。
  • 研究提示词预览可复制。 工具描述保持英文,与模型实际看到的内容一致;预览数值跟随当前草稿。
  • 接管是全局 provider 切换。 它会影响该 DSH profile 中所有使用 ctx.web 的调用,不只本插件。
  • 缓存是进程内内存。 重启后丢失;多进程不共享。
  • DSH preview 兼容范围窄。 当前锁在 0.2.1-rc.2 线,升级 DSH 前先跑回归。

许可证与第三方组件

本项目使用 MIT 许可证,见 LICENSE。

第三方组件与许可证说明见 THIRD_PARTY_NOTICES.md。主要运行时依赖包括 @mozilla/readability、linkedom、cheerio、turndown、@joplin/turndown-plugin-gfm、undici、lru-cache、normalize-url、ipaddr.js、impit(Apache-2.0,平台原生二进制)和 pdfjs-dist(Apache-2.0)。jina-reader 只调用用户配置的 Reader 服务,不打包 Jina 的代码;自托管 Reader 的许可证与运行要求由 Reader 项目提供。wire-http 不打包浏览器、Reader 或 Jina 代码。


如果这个插件对你有帮助,欢迎在 GitHub 提 issue 或 discussion。安全问题请不要公开贴 token、实例密码或完整配置。

—/ 5

No ratings yet

Verified DSH bundle

Commit 7f3c49f8aa14

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