dsh-web-search-searxng
Verified@lathly/dsh-web-search-searxng · v0.1.0 · MIT
Self-hosted SearXNG search provider plugin for the DSH web capability seam (ctx.web)
Install
dsh plugin add @lathly/dsh-web-search-searxng Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Creators
Readme
@lathly/dsh-web-search-searxng
面向 DeepSeek Harness 的自托管 SearXNG 搜索提供方插件。Harness 通过你自己的 SearXNG 元搜索实例检索网络:不需要 API key,也没有第三方能看到查询。
English | 中文
这个包为什么存在
DSH 自带三个搜索提供方:deepseek、exa、perplexity。三者都需要 key,三者都会把查询发给第三方。这一族里没有自托管选项。
本插件在同一个公开接缝 ctx.web.registerSearchProvider 上注册第四个提供方,让部署把查询和引擎组合留在自己的硬件上。它是独立发布的包,装进任何 DSH 部署即可,不需要 fork 仓库。
安装
npm install @lathly/dsh-web-search-searxng
DSH 各包声明为 peerDependencies,因此插件使用宿主自带的 @deepseek-ai/cordis、@deepseek-ai/dsh-web、@deepseek-ai/dsh-launch-environment 与 @deepseek-ai/schemastery。同一进程里出现第二份 Cordis,插件拿到的 web 服务就会与宿主的不同;这一布局正是为了避免该故障。
经过测试的版本是 0.2.1-alpha.2 一线:@deepseek-ai/dsh-web 0.2.1-alpha.2、@deepseek-ai/dsh-launch-environment 0.2.1-alpha.2、@deepseek-ai/cordis 4.0.5-alpha.1、@deepseek-ai/schemastery 3.18.5-alpha.1。
你的实例
SearXNG 必须提供 JSON API。在 settings.yml 中:
search:
formats:
- html
- json
没有 json 的实例会返回 HTML 正文,每次搜索都以 WEB_PROVIDER_ERROR 失败。
挂载
本包附带 bundle patch,因此能解析到该包的 DSH bundle 会自动挂载它:
- name: '@deepseek-ai/dsh-web'
- name: '@lathly/dsh-web-search-searxng'
或写进 profile overlay:
- insert:
- id: web-search-searxng
name: '@lathly/dsh-web-search-searxng'
config:
baseURL: http://localhost:8888
提供方以 searxng 身份注册。当它是唯一可用的搜索后端时,ctx.web.search() 会自动解析到它。若同时存在其他可用提供方,请用 searchProvider: searxng 指定;deepseek-official 在没有 API key 时仍报告为可用,因此两者并存的部署必须指定其一,否则每次搜索都以 WEB_PROVIDER_AMBIGUOUS 失败。
配置
实例地址按此顺序解析:config.baseURL,然后启动环境中的 $SEARXNG_URL,最后是包内默认值 http://localhost:8888。
| 字段 | 默认值 | 含义 |
|---|---|---|
baseURL |
$SEARXNG_URL,然后 http://localhost:8888 |
SearXNG 实例地址;请求时追加 /search。无法解析的值会使提供方不可用 |
engines |
(未设置) | 逗号分隔的引擎白名单,作为 SearXNG 的 engines 发送。它只在实例自身已配置的引擎内收窄 |
categories |
(未设置) | 逗号分隔的分类,作为 SearXNG 的 categories 发送 |
一次搜索返回什么
每条 SearXNG 结果映射为一个 WebSearchSource:url、非空的 title、去除首尾空白的 content 作为 snippet,以及引擎提供时的 publishedDate 作为 publishedAt。没有 URL 的条目被丢弃。引擎扇出产生的重复 URL 保留第一条。
非空的 answers[] 会并入结果的 content。这是该族中唯一能携带生成式答案的后端,因为 SearXNG 的答案块已经存在于线路上。实例没有可生成答案的引擎时,就没有 content。
SearXNG 没有结果数量参数,因此请求的 maxResults 在服务侧约束最终来源,而不是约束请求本身。实例自身的扇出仍会完整执行。
失败
提供方失败(HTTP 错误、网络失败、无法解析或结构不符的正文)以 WebError 呈现,代码为 WEB_PROVIDER_ERROR。被中止的请求呈现为 WEB_ABORTED。重定向在联系 Location 目标之前即被拒绝,因此行为异常或被劫持的实例无法把查询转发到其他来源。
当实例地址无法解析,或某个过滤器被设置为空值时,提供方不可用,每次搜索调用都以结构化错误失败。
模型体验
经由 dsh-tool-web 间接呈现。该消费者保留本提供方受 maxResults 约束的 URL、标题、摘要、发布日期与实例答案块,或保留其原样的 SearXNG search aborted、SearXNG search request failed: <error>、SearXNG returned an unprocessable response body: <error> 失败文本,并套用消费者自身的错误包装。
不直接失效 KV 缓存;请求前缀的任何变化由该消费者负责。
设计说明
本提供方是 SearXNG JSON API 之上的薄适配层,带有三条刻意规则。
- 结构上无凭据。 SearXNG 的 API 不需要 key,因此没有可泄露的东西。提供方仍然选择加入该族的重定向拒绝策略。
- 只使用可移植来源。 来源的
snippet只来自 SearXNG 的content字段。空白或带填充的值会被裁剪或省略,绝不编造。 - 诚实的答案。
answers[]是实例自己的自由文本块。它被并入content而不是丢弃。
search() 请求 {baseURL}/search?q=<query>&format=json,可带 engines 与 categories 参数,并使用 redirect: 'error'。解析出的 results[] 逐条映射,无 URL 的条目丢弃,重复项去除,服务在返回途中施加最终的 maxResults 约束。中止(名为 AbortError 的 DOMException)转为 WEB_ABORTED;其他情况转为 WEB_PROVIDER_ERROR。
已知限制
- 实例必须启用 JSON API。 只有 HTML 的实例会使每次搜索以
WEB_PROVIDER_ERROR失败,而不是 harness 能够报告的配置错误。 - 实例侧控制未暴露。 引擎组合、默认分类与答案块取决于实例的
settings.yml与引擎集合。engines与categories只在其中收窄。 maxResults在扇出之后生效。 实例先取回完整结果集,服务再截断,因此较大的实例答案要付出其完整延迟。- 中止判定依赖错误形态。 只有名为
AbortError的DOMException映射为WEB_ABORTED。携带自定义原因的中止,例如dsh-timeout的TimeoutReason,会呈现为WEB_PROVIDER_ERROR。 - API 尚未稳定。 DSH 的 API 处于 pre-stable 阶段。改变
WebSearchProvider的 DSH 版本可能破坏本插件;测试套件会最先暴露这一点。
开发
pnpm install
pnpm run typecheck # 针对已发布的 DSH 包做类型检查
pnpm run test # 26 个单元与真实组合测试,无需实例
pnpm run test:e2e # 真实实例冒烟测试;实例无响应时自动跳过
pnpm run build # 产出 lib/*.js 与 lib/types/*.d.ts
| 文件 | 职责 |
|---|---|
src/index.ts |
插件入口:配置 schema、环境变量回退、提供方注册 |
src/provider.ts |
SearxngSearchProvider:请求分发、中止分类、结果映射 |
src/types.ts |
SearXNG 线路类型:SearxngResponse、SearxngResult |
待办:SearXNG 的 time_range、safesearch、language 控制仍未暴露。暴露它们需要先有提供方中立的服务字段,让这一族加入一个统一控制,而不是某个厂商专用的参数。
与上游的关系
该提供方也存在于 DSH 仓库内,包名 @deepseek-ai/dsh-web-search-searxng,路径 packages/web/web-search-searxng。那份副本是 fork 仓库所携带的版本。本包是同一个提供方的独立发布,目的是让不改动上游的部署也能把搜索留在自己的硬件上。