前言¶
DeepSeek Harness(DSH)桌面版在本机用明文 HTTP 监听时,每次启动会绑定新的临时端口,会话 Cookie 的名字会随 host:port 变化而不断新增,旧条目又不会被上游回收。重启次数一多,启动握手会把整个 Cookie jar 打进请求头,撞上 Node 默认约 16 KB 的 max-http-header-size,界面表现为 desktop welcome: Web authentication failed,弹窗却建议重装或禁用插件——两者都不对症。
下面介绍社区插件 dsh-cookie-janitor(维护者 dududreamer,分类:客户端)。它不做「一键清空 jar」,而是在每次签发新会话 Cookie 时,把同批请求里其余 dsh-auth-* 名字用 Max-Age=0 收敛掉,让桌面壳在故障复发前回到「每次启动只净增一条有效 Cookie」的稳态。
这是什么¶
dsh-cookie-janitor 是 DSH 的 Cordis 客户端插件(npm 包名 dsh-cookie-janitor,版本 1.0.0,MIT 许可证)。它挂载在连接层的授权握手与已认证 API 响应路径上,针对本机 127.0.0.1 下因端口随机化而堆积的 dsh-auth-<hash> Cookie 做收敛,避免启动时 Cookie 头过大导致 431 Request Header Fields Too Large,进而被宿主报成 Web 认证失败。
插件以当前 DSH 进程权限运行;安装前请自行阅读 GitHub 仓库 源码与许可证。社区目录页:skillhub.cn/plugins/dududreamer/dsh-cookie-janitor(独立站点,与 DeepSeek / 幻方无官方从属关系)。
故障形态与根因(简要)¶
桌面版启动参数使用 --port 0,requestAudience() 对明文 HTTP 返回的 authority 含端口;Cookie 名称为 dsh-auth- 加 base64url(sha256(authority)),且未按端口隔离,也没有上游 cookies.remove 逻辑。每启动一次多一条、旧条保留 30 天,实测约在约第 72 条 Cookie 对时越界——只有启动握手那一发 credentials: "include" 会带上整 jar,故形态固定为「启动即失败」,运行期反而正常。
HTTPS 部署下 authority 通常不含端口,一般不会堆积;该插件主要面向本机明文 HTTP 场景。
核心功能¶
经 README 与 package.json 描述,插件能力可归纳为:
- 授权握手收敛:在
connection.authorizeIndex/connection.authorizeConnect响应中,以本次set-cookie要签发的名字为保留项,对其余请求里出现的全部dsh-auth-*追加删除指令(Max-Age=0),且删除行排在有效set-cookie之前,同名字后者覆盖前者,避免误删当前会话。 - 运行期 API 收敛:在
connection/requestwaterfall 里,用base64url(sha256(host))推算当前 Cookie 名;仅当该名确实出现在请求头时才清理其它dsh-auth-*,否则跳过——失败模式是「不动手」,代码路径里没有整 jar 清空。 - 可观测日志:默认把动作追加到系统临时目录下的
dsh-cookie-janitor.log;设环境变量DSH_COOKIE_JANITOR_LOG=off可关闭。
安装与启用¶
官方说明要求 DeepSeek Harness 桌面版,且能写入 $DSH_HOME(默认 ~/.dsh)与当前 profile 目录。DSH 生态里扩展以本地插件 + profile 补丁层挂载为主;没有 dsh plugin add github:... 一类一键命令,需按仓库 README 手动放置并链接。
1. 放入 local-plugins¶
仓库 README 给出的获取与拷贝方式如下(需本机已安装 git):
git clone https://github.com/dududreamer/dsh-cookie-janitor.git
mkdir -p "$DSH_HOME/local-plugins"
cp -r dsh-cookie-janitor "$DSH_HOME/local-plugins/"
Windows PowerShell:
git clone https://github.com/dududreamer/dsh-cookie-janitor.git
New-Item -ItemType Directory -Force "$env:USERPROFILE\.dsh\local-plugins" | Out-Null
Copy-Item .\dsh-cookie-janitor "$env:USERPROFILE\.dsh\local-plugins\" -Recurse
2. 链接进 profile 的 node_modules¶
Windows(Junction):
$scope = "$env:USERPROFILE\.dsh\profiles\desktop\node_modules"
New-Item -ItemType Junction -Path "$scope\dsh-cookie-janitor" `
-Target "$env:USERPROFILE\.dsh\local-plugins\dsh-cookie-janitor"
macOS / Linux:
ln -s "$DSH_HOME/local-plugins/dsh-cookie-janitor" \
"$DSH_HOME/profiles/desktop/node_modules/dsh-cookie-janitor"
3. 在 profile 补丁层激活¶
编辑 $DSH_HOME/profiles/desktop/cordis.patch.yml,在末尾追加:
- insert:
- id: dsh-cookie-janitor
name: dsh-cookie-janitor
config: {}
在 profile 的 package.json 中声明依赖,避免后续 pnpm install 清掉链接:
"dependencies": {
"dsh-cookie-janitor": "file:../../local-plugins/dsh-cookie-janitor"
}
4. 生效¶
若 profile 为 patchReload: live,改完补丁层可热加载,无需为了「试插件」再重启桌面壳——而反复重启恰恰是触发 Cookie 堆积的条件之一。
验证与典型日志¶
插件不写 UI,验证应看日志而非 Network/Cookies 文件体积(SQLite 页回收后文件可能延迟缩小)。日志路径为 <tmpdir>/dsh-cookie-janitor.log,README 示例:
2026-11-01T09:11:18.656Z apply loaded (pid 37868)
2026-11-01T09:11:19.676Z authorize: collapsing 39 stale cookie(s), keeping the one being issued
2026-11-01T09:11:30.173Z apply loaded (pid 14520)
2026-11-01T09:11:31.120Z authorize: collapsing 1 stale cookie(s), keeping the one being issued
第一次可能清掉数十条历史条目;稳态后每次启动通常只清 1 条陈旧项,与 README 描述一致。
回滚¶
任选一步即可停用:
- 删除
cordis.patch.yml末尾的dsh-cookie-janitorinsert 段; - 删除 profile 下
node_modules/dsh-cookie-janitor链接。
手动删掉 Network/Cookies 只能临时救场一次,不装插件时故障仍会随重启复发。
适用场景与注意¶
适合:已在桌面版遇到 desktop welcome: Web authentication failed、且根因是本机明文 HTTP 下 dsh-auth-* 堆积的用户,在 upstream 修正端口进 Cookie 名或增加 prune 之前,需要本机可用的收敛方案。
不必装:HTTPS 部署或从未出现启动即认证失败的情况。
边界:上游若更改 Cookie 命名算法,waterfall 侧会因算出的名字不在请求头而静默停手,届时需同步插件逻辑;授权侧仍依赖响应自带的 set-cookie 名字。更完整的证据链见仓库 docs/root-cause.md。
结尾¶
dsh-cookie-janitor 用「收敛而非清空」的方式,把端口随机化带来的 dsh-auth-* 堆叠压回单条有效会话,避免 Node 请求头预算在启动握手处被耗尽。目录页:https://www.skillhub.cn/plugins/dududreamer/dsh-cookie-janitor;源码与安装细节:https://github.com/dududreamer/dsh-cookie-janitor。