DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

yan3536 /

yan3536/dsh-cookie-janitor

Verified

DeepSeek Harness plugin: stops stale dsh-auth-* cookies from overflowing the request header and causing HTTP 431 / blank screen

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHubProject homepage
READMESource: main@ec3a1225

dsh-cookie-janitor

test license

DSH 启动越来越慢、最后白屏或直接起不来?多半是浏览器里堆积了几十条过期的登录 cookie。

这个插件在请求进入应用之前把它们清掉。装上之后不需要任何操作,也不会改变登录状态。


问题是什么

DSH 的浏览器认证给每个监听地址签一条 cookie,名字是算出来的:

cookie 名 = "dsh-auth-" + base64url(sha256("host:port"))

名字里带了端口。而端口是变的:

  • 桌面版启动时写死了 --port 0,让操作系统挑空闲端口(@deepseek-ai/dsh-desktop-host 的 runProfile({ args: ["--no-open","--host","127.0.0.1","--port","0"] }));
  • 命令行 dsh --profile web --port 0 同理。

所以每次启动都是一个新端口、一个新名字。

cookie 的归属范围只到主机,不含端口。浏览器对 127.0.0.1 发出的每一个请求,都会把历史上所有 dsh-auth-* 一起塞进 Cookie 头——哪怕那些端口早就没人监听了。

cookie 的有效期是 30 天,且不因使用而续期。所以:

30 天内启动 N 次,就堆 N 条无用的 cookie。

单条约 221 字节。Node.js 的请求头上限是 16 KiB,超过就返回 431 Request Header Fields Too Large,而且是在应用代码跑起来之前——页面拿不到任何有用信息,表现就是白屏、加载卡住、或认证失败。

实测:73 条时 Cookie 头 16277 B 仍能通过,74 条时 16500 B 拿到 431。因为 Host、User-Agent 等头也占同一份额度,实际触顶会略早于这个数,按 70 条左右估算。一天开几次、开一个月,就会撞上。

它做什么

三层,按发生顺序:

层 时机 动作
请求入口 每个请求 从 Cookie 头里摘掉属于其他端口的 dsh-auth-*,应用根本看不到它们
响应出口 同一请求 给被摘掉的那些下发 Max-Age=0,让浏览器把垃圾从库里删除
溢出兜底 431 发生前 如果请求头已经大到 Node 拒绝解析,就把 431 换成一次 302 回到原地址,并附上清除指令——用户看到的是刷新一下,而不是崩溃

当前正在用的那条 cookie 永远不动。 删掉它会把你从正在使用的实例里登出。

清完之后,第二次请求的 Cookie 头就只剩一条,之后不再增长。

安装

从 Git 仓库装:

dsh plugin --profile web add github:yan3536/dsh-cookie-janitor

或先克隆到本地再用绝对路径装(改源码调试时用这个):

git clone https://github.com/yan3536/dsh-cookie-janitor
dsh plugin --profile web add /绝对路径/dsh-cookie-janitor

装完完全退出 DSH 再启动(不是刷新页面,是退出进程)。插件挂在 Host 的 HTTP 服务上,只有在启动时才能装上。

桌面版用户把 --profile web 换成 --profile desktop;但桌面版 profile 被 Electron 独占,必须先完全退出 DSH 再执行命令,否则会得到 Open DeepSeek Harness Desktop once to initialize its profile, then fully quit it before running dsh plugin --profile desktop.

卸载:

dsh plugin --profile web remove dsh-cookie-janitor

配置

全部可选,默认值就是推荐值。想改就写进 profile 的 cordis.patch.yml:

- id: cookie-janitor
  name: dsh-cookie-janitor
  config:
    keepForeign: 0        # 允许保留几条非当前端口的 cookie;0 = 全清
    pruneRequests: true   # 关掉就只剩溢出兜底
    rescueOverflow: true  # 关掉则 431 原样返回
    maxHeaderBytes: 0     # >0 时把 Node 的头上限抬到这个字节数
    attachTimeoutMs: 15000

maxHeaderBytes 只是把症状往后推——真正止血的是 keepForeign: 0。除非你有特殊理由(同一浏览器要同时连多个 DSH 实例),否则别动它。

想同时连多个实例的话,把 keepForeign 设成你实际并用的实例数,插件会按浏览器发送顺序保留最新的那几条。

会不会误删

不会。判定完全按 DSH 自己的算法来:

  • 只碰 dsh-auth- 开头的 cookie,其他 cookie(主题、语言、第三方)一律不动;
  • 当前 Host 对应的那条永远保留;
  • 被删的那些,其对应的监听端口在当前进程里根本不存在,留着也没有任何用处。

如果哪天 DSH 换了 cookie 命名规则,插件会识别不到任何 dsh-auth-*,于是什么都不做——最坏情况是退回原状,不会误删。

手动清理(不装插件)

如果只想先把眼前的崩溃解决掉,在浏览器里清掉 127.0.0.1 的站点数据即可:

  1. 打开 http://127.0.0.1:<端口>;
  2. 地址栏左侧的站点信息 → Cookie 和网站数据 → 删除;
  3. 或者开发者工具 → Application → Cookies → 逐个删掉 dsh-auth-*。

但这只治一次。下次启动还是会产生新的一条,只是重新开始攒。

离线自测

node test/smoke.mjs

24 个用例,不依赖 DSH、不联网:

  • 16 个纯函数(cookie 名推导、authority 归一化、Cookie 头解析、清理策略的六种情形、过期指令拼装、原始报文与 target 抓取);
  • 6 个端到端(真实 node:http 服务器 + 裸 socket):正常请求透传、干净请求逐字节不变、20 KiB 头被救成 302、关掉兜底后恢复原生 431、放宽上限生效、关掉清理后原样透传;
  • 2 个健壮性(没有 web 服务时静默、畸形配置不抛)。

兼容

在 DSH 0.2.0-rc.2 上实测通过。Node ≥ 20(用到 Buffer.toString('base64url') 与 replaceAll)。

插件不声明 engines.dsh。DSH 的兼容检查一旦看到这个键就按它独占判定,而预发布版(0.2.0-rc.2)低于 0.2.0,写上 >=0.2.0 反而会把当前能用它的版本挡在外面。宁可让它跑,也不要在清单层面自己设卡。

插件只用 webServer 服务的两个公开成员:server(node:http 的 Server 实例)和 protocol('http:' 或 'https:')。这两个在 dsh-host-webserver 的 lib/index.js 里是明文类字段与 getter(:281、:305-307),运行期一定存在。

它不复用任何未导出的内部符号:cookie 名是自己按 sha256(authority) + base64url 复算的,因为 BrowserAuth、COOKIE_PREFIX、cookieName 三者都没有从 @deepseek-ai/dsh-client-connection 导出(该包 lib/index.js:1072 的 export 列表里没有它们)。

如果哪天 DSH 改了 cookie 命名规则,插件会扫不到任何 dsh-auth-*,于是什么都不做——最坏情况是退回原状,不会误删。

已知边界

  • 只覆盖 Host 自己的 HTTP 监听。桌面版主窗口走 dsh-app:// 自定义协议,它的认证 cookie 由主进程内存变量持有、经请求头注入,不写浏览器 cookie 库,因此不在此插件的处理范围内——那条路径本来也不会堆积。
  • 清理发生在下次请求时,不是安装的那一瞬间。装完第一次打开页面,插件才会看到并清掉旧 cookie。如果此刻请求头已经超限,走的是「溢出兜底」那条路:一次 302,然后清干净。
  • 不改 DSH 的端口策略。--port 0 是给远程访问留的正规能力,插件只在 cookie 侧做减法。

许可

MIT。

—/ 5

No ratings yet

Verified DSH bundle

Commit ec3a1225aa18

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