前言¶
在 DSH 里接 LM Studio 等本地推理服务时,长上下文 prefill 往往要安静算很久。若请求在恰好五分钟后失败,客户端报 terminated,模型端日志却是 Client disconnected,很容易先怀疑 DSH 或 provider 的 streamIdleTimeoutMs。实际上,Node 内置 fetch 走 undici,连接级 bodyTimeout 默认 300,000ms,且是「空闲计时」:prefill 阶段没有 body 字节时计时器不会重置,五分钟后 undici 会直接销毁 socket。下面介绍社区插件 dsh-undici-timeout-fix(维护者 lilinhua0413,分类:模型推理)如何在不改 DSH 本体的前提下处理这一层限制。
这是什么¶
dsh-undici-timeout-fix 是一个 DSH Cordis 插件(npm 包名 dsh-undici-timeout-fix,当前资料中的版本为 1.1.0,MIT 许可)。它通过替换 undici 的全局 dispatcher,将 headersTimeout 与 bodyTimeout 设为 0(表示禁用计时器,而非设成某个时长),从而避免本地模型长时间 prefill 时被 undici 的 300 秒 body 超时切断。
DSH 经 @deepseek-ai/dsh-llm-pi-ai(pi-ai)调用 OpenAI 兼容 SDK,该 SDK 使用全局 fetch(Shims.getDefaultFetch())。插件在加载时安装 dispatcher,因此覆盖模型相关 HTTP 请求,无需 patch DSH 核心。
问题与 streamIdleTimeoutMs 的区别¶
本地模型 prefill 超过约五分钟后,典型现象是请求以 terminated 结束,服务端出现 Client disconnected。原因不在 DSH 某一项「总超时」开关,而在 undici 默认 bodyTimeout: 300_000ms。
streamIdleTimeoutMs 配置的是 DSH / pi-ai 自己的流空闲看门狗,是另一套计时器。在未装本插件前,它也在 300,000ms 处可能触发;仅把 streamIdleTimeoutMs 调大,往往只是让 undici 先触发,报错会从 stream idle timeout after 300000ms 变成单纯的 terminated。本插件针对的是 undici 传输层;装插件之后仍建议为本地 provider 单独配置足够大的 streamIdleTimeoutMs,作为有限兜底(见下文)。
核心功能¶
- 插件加载时执行
setGlobalDispatcher(new Agent({ headersTimeout: 0, bodyTimeout: 0 })),禁用 undici 连接级 header/body 空闲超时。 - 通过 Cordis patch 注册插件 id
undici-timeout-fix,与 DSH 插件体系集成。 - 依赖
undici(package.json 中为^8.10.2),要求 Node>=22.19。 - README 说明:未声明
peerDependencies,一般不会被 DSH 插件版本兼容性检查拦截。
安装与启用¶
安装前请自行查看 GitHub 仓库 源码与 MIT 许可证。插件在 DSH 进程权限下运行,与任何第三方插件一样,安装即信任其代码行为。
从 Release 包安装(不依赖插件 registry)¶
从仓库 Releases 下载 dsh-undici-timeout-fix-1.1.0.tgz,再执行:
dsh plugin --profile <your-profile> add /path/to/dsh-undici-timeout-fix-1.1.0.tgz
依赖 undici 仍会从你能访问的 npm registry(或内网镜像)解析。
从 npm 安装¶
dsh plugin --profile <your-profile> add dsh-undici-timeout-fix
也可在 DSH 插件管理界面添加包名 dsh-undici-timeout-fix,并将安装源指向提供该包的 registry。若 pnpm 的 minimumReleaseAge(默认 24 小时)导致装到旧版本,可指定:
dsh plugin add dsh-undici-timeout-fix@1.1.0
手动写入 patch¶
在 profile 的 cordis.patch.yml 中增加:
- insert:
- id: undici-timeout-fix
name: 'dsh-undici-timeout-fix'
必须完全重启 DSH¶
dispatcher 在插件加载时设置;已运行进程不会热更新。完全退出 DSH 后再启动(macOS 需 Cmd+Q,仅关窗口不够)。README 指出,漏重启是「装了仍失败」最常见原因。
典型配置:本地 provider 的 streamIdleTimeoutMs¶
本插件去掉传输层 300 秒上限后,DSH 侧若没有有限看门狗,真正卡死的连接可能长期挂起。应对每一个指向本地模型的 provider 设置足够大但有限的 streamIdleTimeoutMs;未配置的 provider 仍退回默认 300,000ms。
示例(来自 README,字段名与结构请按你实际 profile 调整):
- id: llm-pi-ai
name: "@deepseek-ai/dsh-llm-pi-ai"
config:
providers:
lmstudio1:
displayName: lmstudio
apiKeyEnv: LMSTUDIO1_API_KEY
api: openai-completions
baseURL: http://127.0.0.1:1234/v1/
streamIdleTimeoutMs: 1800000 # 30 分钟
models:
- id: qwen3.5-122b-a10b
name: qwen3.5-122b-a10b
若不想完全禁用 undici 计时,可在自研或 fork 中采用有限值(README 示例为 3,600,000ms);本插件默认策略是 0 表示禁用。
验证与排错¶
- 发送一次 prefill 明显超过五分钟的请求;若正常完成,说明修复已生效。
- 根据报错区分计时来源:
| 报错 | 含义 |
|---|---|
terminated |
undici 传输层——本插件负责 |
pi-ai stream idle timeout after xxxms |
DSH 看门狗——增大对应 provider 的 streamIdleTimeoutMs |
适用场景与注意¶
适合谁: 在 DSH 中通过 OpenAI 兼容接口调用本地大模型(如 LM Studio),且 prefill 或长时间无 body 输出会超过五分钟的开发者。
代理环境变量: 不要设置 HTTP_PROXY、HTTPS_PROXY、ALL_PROXY。dsh-http-proxy 会在 boot 阶段安装自带五分钟限制的 Agent,并覆盖本插件;DSH 先装 proxy、后加载插件,因此无代理时本插件才可靠生效。
平台: README 记录 macOS(Darwin 24,Node 24.21.0,内建 undici 7.29.1)已测试可用;Windows 尚未验证,代码无平台专用逻辑,欢迎通过 issue 反馈。
生态说明: DSH 采用「一切皆插件」的 Cordis 扩展方式;SkillHub 目录页 为社区收录,与 DeepSeek / 幻方无官方从属关系。
结尾¶
dsh-undici-timeout-fix 把问题定位在 undici 全局 fetch 的默认 body 空闲超时,用最小侵入的方式换全局 dispatcher,并提醒同时配置 streamIdleTimeoutMs 与避免代理插件抢 dispatcher。若你正在排查「本地模型五分钟必断」,可先对照报错表区分 undici 与 pi-ai 看门狗,再按 README 安装并完整重启 DSH。
- 目录页:https://www.skillhub.cn/plugins/lilinhua0413/dsh-undici-timeout-fix
- GitHub:https://github.com/lilinhua0413/dsh-undici-timeout-fix