🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

压缩响应修复 Geighlord007/dshpatch

DeepSeek Harness
Geighlord00742 天前有提交已提供中文文档扫描:无法判定

修复插件读取压缩 JSON 时解析崩溃的问题

29.6/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/9/27 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add Geighlord007/dshpatch
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么[目录]—
dsh 原生插件 · other
暂无时间戳·判据 →
装得上吗[实装验证]—
本站尚未做安装检查
L4 · 真实安装等级说明 →
数据截至 2026/10/05·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/04·判据 →
还在维护吗[仓库]—
更新放缓:最近一次提交在 42 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →

可信度证据

安全扫描自动 · 静态分析源码
v2.7.0
⚪ 扫描:无法判定尚无人工评估
展开查看扫描说明与证据 ↓

已尝试扫描但取不到可分析的源码:仓库或包不存在、已删除,或为非 JS/TS 实现、未随包发布源码。无法判定,不代表安全。

  • · 包内无可扫 JS
  • · TS 源码(可能为非 JS 实现或未发布源码),无法判定
扫描于 2026/11/4(1 天前) · 范围 全包扫描(包内未声明入口) · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

社区实装还没有人打卡 · 装过的第一个就是你
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 修复压缩响应解析崩溃
展开完整介绍(131 字)↓

给通过 Node 内置 fetch 读 JSON 的 DSH(DeepSeek Harness)插件打补丁:undici 8 的全局 dispatcher 会丢掉 content-encoding,压缩过的响应体到 JSON.parse 手里还是原始 gzip。

README

由 DeepSeek 最新模型翻译生成
dshpatch 在 DSH(DeepSeek Harness)0.1.7-rc.1 上,对两个第三方插件的修复补丁。 一句话:DSH 宿主进程里 undici 8 注册的全局 dispatcher 会让 Node 内置 fetch 丢掉 content-encoding,压缩响应于是变成“裸压缩字节”——所有直接用全局 fetch 读 JSON 的插件都会崩。 症状 搜索类工具会报成这样(长得很怪,但很好认): WebError: WEB_PROVIDER_ERROR Error: Exa returned an unprocessable response body: SyntaxError: Unexpected token '', "�"... is not valid JSON Error: Unexpected token '', "�"... is not valid JSON 注意状态码是 200——不是网络错误,是“收到了但读不懂”。
展开完整文档(README 剩余 1 节)
dshpatch

在 DSH(DeepSeek Harness)0.1.7-rc.1 上,对两个第三方插件的修复补丁。

一句话:DSH 宿主进程里 undici 8 注册的全局 dispatcher 会让 Node 内置 fetch 丢掉 content-encoding,压缩响应于是变成“裸压缩字节”——所有直接用全局 fetch 读 JSON 的插件都会崩。

症状

搜索类工具会报成这样(长得很怪,但很好认):

WebError: WEB_PROVIDER_ERROR
Error: Exa returned an unprocessable response body: SyntaxError: Unexpected token '', "�"... is not valid JSON

Error: Unexpected token '', "�"... is not valid JSON

注意状态码是 200——不是网络错误,是“收到了但读不懂”。

根因

三份 undici 同时存在于一个进程:

| 位置 | 版本 | 谁在用 | 说明 |
| Node 22.23.2 内置 | 无版本号(旧世代) | 你的插件里直接写的 fetch() | globalThis.fetch |
| DSH 安装树 dsh/node_modules/undici | 8.11.0 | @deepseek-ai/dsh-http-proxy、dsh-web-fetch-http(web_fetch) | 被注册成全局 dispatcher |
| profile profiles/web/node_modules/undici | 7.29.0 | dshmarket 等 profile 插件 | 插件市场自带的依赖 |

关键机制:npm 版 undici 只要被 import,就会把自己的一份 Agent 注册到
Symbol.for('undici.globalDispatcher.1') —— 这是跨副本共享的注册符号,
而 Node 内置 fetch 也读这个符号。跨大版本之后,响应头被丢掉、响应体仍是压缩的。

实测矩阵(同机、同 Node、同一个 Exa 请求):

| fetch 实现 | 全局 dispatcher | 结果 |
| Node 内置 fetch | 无 | ✅ |
| Node 内置 fetch | app undici 8.11.0 | ❌ 复现(ce=null,body 是裸 gzip) |
| Node 内置 fetch | profile undici 7.29.0 | ✅ |
| undici 8.11.0 自带 fetch | app undici 8.11.0 | ✅ |
| undici 7.29.0 自带 fetch | app undici 8.11.0 | ❌ |

规律:fetch 与 dispatcher 必须来自同一份 undici。

导入顺序实验(tools/exa-dispatcher-trigger.mjs):

刚启动 dispatcher=none 内置 fetch OK import 8.11.0 之后 dispatcher=Dispatcher1Wrapper 内置 fetch BROKEN 先 import 7.29.0 dispatcher=Agent 内置 fetch OK 再 import 8.11.0 dispatcher=Dispatcher1Wrapper 内置 fetch BROKEN ← v8 会覆盖

所以触发时刻是:进程里第一次走到会 import npm undici 的路径(例如第一次用 web_fetch)之后,所有用全局 fetch 的插件都开始中招。这解释了“同一台机器上,先好好的,后来突然全报错”。

补丁

| 补丁 | 目标 | 改动 |
| patches/qp-exa-dynamic-0.1.0.patch | qp-exa-dynamic@0.1.0 → lib/index.js | 请求头加 accept-encoding: identity;响应体改由新增的 readSearchBody() 读取(先取字节,按魔数解 gzip / zstd,brotli 兜底,容忍 BOM) |
| patches/dsh-find-plugin-0.3.7.patch | dsh-find-plugin@0.3.7 → lib/github.js、lib/registry.js | 同上;新增共用模块 lib/safe-json.js(导出 readJson 与 IDENTITY_ACCEPT_ENCODING) |

设计原则:与 undici 版本彻底解耦 ——不依赖任何一份 undici 的解压行为,同时不绕过 DSH 的代理策略(仍然走全局 dispatcher 发请求)。

用法

默认路径($env:USERPROFILE\.dsh\...) pwsh -File .\apply.ps1

自定义 profile / 插件目录 pwsh -File .\apply.ps1 -Profile "D:\other\.dsh\profiles\web" -ExaPlugin "D:\other\plugins\qp-exa-dynamic"

脚本会先 git apply --check,通过才应用;已打过补丁会自动跳过。
改完必须重启 DSH 才生效(插件不做热重载)。

手动应用单个补丁:

cd "$env:USERPROFILE\.dsh\plugins\qp-exa-dynamic"
git -c core.autocrlf=false apply "\patches\qp-exa-dynamic-0.1.0.patch"

-c core.autocrlf=false 不能省:否则 Windows 上的 git 会改写行尾,补丁结果与预期不一致。

验证

node tools\identity-demo.mjs # 演示 identity 头的作用(压缩 vs 不压缩)bash
node tools\exa-dispatcher-trigger.mjs # 证明“import 即注册”与覆盖顺序
node tools\find-plugin-verify.mjs # 在坏环境下验证补丁后的插件
node tools\plugin-fetch-exposure.mjs # 扫描本机哪些插件暴露(宿主端裸 fetch)

实测输出节选(在故意装上坏 dispatcher 的环境里):

control res.json()-style: ce=null magic=1f8b -> BROKEN (raw compressed body)
patched searchGitHub("pet"): 5 hits
patched loadRegistry(): source=live plugins=4225

qp-exa-dynamic 自带单元测试:node test/index.test.js → 40/40 通过。

为什么用 accept-encoding: identity

服务器通常会压缩响应省流量,压缩件靠 content-encoding 这个“标签”来告诉客户端要不要拆压。
本 bug 就是标签被撕了但货还是压缩的。直接要求“别压缩”,就没有拆压这一步,标签丢了也无所谓。

代价只有传输体积:同一个响应 5.0 KB → 13.2 KB。
解码后的内容大小完全一致,所以它不影响工具输出的长度,也不影响模型上下文/token 消耗。

注意

- 补丁改的是 pnpm 安装目录里的包,下次安装/更新这些插件会被覆盖 → 重新跑 apply.ps1 即可(脚本可重复执行)。
- 不建议为此降级 undici:两份 undici 各有其主(app 那份服务 DSH 自带组件的 zstd 等能力, profile 那份是插件市场的依赖),降级会牵动别的插件。补丁侧解决更干净。
- 浏览器端插件不受影响:lib/client.js 跑在页面里,用的是浏览器的 fetch(另一套实现)。
- 只有“宿主端 + 直接调全局 fetch + 对方返回压缩响应”三条同时成立才会中招。
- 上游更值得修:@deepseek-ai/dsh-http-proxy 注册的全局 dispatcher 与宿主 Node 内置 undici 跨大版本。

复现与证据

- 全部结论都出自本机对照实验,脚本在 tools/,都可在本机直接重跑。
- 同一请求的两组实测:
- 压缩传输 5,007 字节,content-encoding: null,JSON.parse 失败
- 不压缩 13,213 字节,content-encoding: null,正常解析出 3 条结果

License

MIT
预览分享卡片长什么样 ↓Geighlord007/dshpatch
分享 · DeepSeek Harness Hub
Geighlord007/dshpatch

修复插件读取压缩 JSON 时解析崩溃的问题

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部