thu-tok-auto

modelnpmMIT

Fetches Tsinghua MadModel API tokens and renews them from the saved SSO session on a 20-minute timer in a windowless browser, writes the token into the DSH credential MADMODEL_API_KEY and creates or reuses the madmodel model provider; one manual Get captures that session through the campus login win

下载量 / Downloads
365

Install

dsh plugin --profile web add thu-tok-auto

Sandbox test

This plugin has not been tested yet. Submit a test →

README

thu-tok-auto(THU Tok Auto)

DSH / DeepSeek Harness 的 Cordis 插件:一键获取清华大学 MadModel 平台

(madmodel.cs.tsinghua.edu.cn)的最新 API token,自动写入 DSH 模型配置,

并支持到时自动续期。当前版本 0.3.24;更新内容见 [CHANGELOG](./CHANGELOG.md),

使用边界见 [已知限制](./docs/KNOWN_LIMITATIONS.md)。

  • Get:立即续期。依次尝试「用现有凭据签发新令牌 → SSO 重放 → 复用现有令牌」,

成功后写入 DSH 凭据 MADMODEL_API_KEY 并自动创建/复用模型 Provider

llm-pi-ai.providers.madmodel。手动点 Get 不会被"现有令牌还有效"短路:

自动路径都刷不出新令牌时它会直接打开登录窗口,并且这一次点击就够了 ——

登录完成后插件自己捕获、校验、写凭据、同步 Provider,无需再点第二次;

等待期间控件会写着「等待登录」。

  • Auto:开关自动续期。开启后每满 20 分钟自动触发一次,任务运行在 Host 侧,

与页面是否打开无关,也不依赖任何浏览器一直开着。后台永远不弹登录窗口——

无人看管的机器上不该自己长出窗口;刷新不了就如实显示「需要登录」,等你点 Get。

这个间隔是量出来的、不是猜的:2026-10-04 在本机测到,重放所需的 IDP 会话在真实登录后

~45 分钟仍被认得、70 分钟已经失效,而令牌本身有 6 小时——按小时排计划,多数尝试会落在

已经死掉的会话上。这是单机观察,不能保证所有账号的会话都能持续这么久。

失败重试有退避(5 分钟起翻倍,上限 30 分钟),但令牌剩余不足 1 小时时退避降回 5 分钟,

免得一记退避把下一次尝试拖过了期。

  • 计时器:显示「距最近一次 Get 的本地经过时间」hh:mm(超过 99 小时停在 99:xx)。
  • 状态不只在悬停里:健康时控件保持安静;一旦需要你动手(需要登录 / 令牌过期 /

续期未生效)或只完成了一半(令牌已更新但模型配置没写进去),控件会在下一行用文字

说明,同时改圆点颜色——不靠颜色单独表意,也不用悬停才看得见。

悬停另有完整信息:状态、上次获取时间、Token 剩余有效期与 Auto 说明,

以及上一次点击与上一次自动运行各自的判据(哪一级阶梯给的令牌、服务端是否确认、

用时、有没有开登录窗口)——两者分开记,因为整点自动运行会把「上一次运行」覆盖掉,

而被吞掉的那次点击恰恰是最需要留下证据的。

续期通道(2026-09-29 实测变更)

站点的免登录签发端点 /model-api/auth-login/check 已不再允许无凭证签发

(返回 10001 ticket已过期或无效,请重新登录);保存的 SSO 会话过期后,

/model-api/auth-login 会返回 10003 抱歉哦,您无此权限。插件因此按下面的顺序续期:

1. 用现有凭据签发 —— 站点已关闭免登录签发,通常直接失败(返回 10001);

2. SSO 重放 —— 用保存的 cookie 走一遍统一认证链取一次性 ticket,再换令牌。

这条也是登录窗口捕获失败时的兜底:登录成功后页面即使还没把令牌写进

localStorage,新拿到的 SSO cookie 也能直接换成令牌;

这条链需要浏览器算设备指纹时,插件用自己启动的那台无窗口浏览器补最后一步:

先把保存的会话按域/路径写进它,再让它访问登录入口 —— 会话不先交进去,那台浏览器

读到的永远只是登录页(这条以前是缺的,无窗口续期因此一直走不通);

3. 复用现有令牌 —— 仍然有效就直接用:控件保持绿灯,不报警;

4. 打开登录窗口 —— 只在你手动点 Get 时(哪怕手上那枚旧令牌仍可用,因为你点它就是要

刷新,而登录是唯一还能刷新的门)。打开后这一次点击就够了:插件每 2.5 秒看一次那个

窗口,登录完成即自动捕获→校验→写凭据→同步 Provider,然后把它自己开的窗口关掉。

后台 Auto 永不弹窗。

5. 判据:拿到令牌先比 exp —— 同一张令牌回来时(会话没变,站点就返回原来那串)

不算刷新成功:状态显示「刷新未生效:到期时间未前进」,圆点转橙,而不是继续显示 ok。

登录状态是怎么留住的:插件在登录窗口还开着时读取 cookie 与页面令牌,

将会话材料保存到本地,令牌写入 DSH 凭据服务。会话 cookie 通常不会由浏览器常规持久化;

插件恢复保存的 cookie 后能否继续使用,仍由服务端的过期、撤销与设备校验决定。

Cookie 按全量保存,请求时按目标 URL 逐跳筛选(域 + 路径 + secure + 未过期),

跨 id. / oauth. / auth*.tsinghua.edu.cn 与 madmodel 都会带上对应的一份。

由此:登录窗口用完就会自动关闭(成功捕获之后,或超时/你手动关掉/插件卸载时),

不需要你留着它 —— 但这也意味着续期靠的是那份保存下来的会话材料:

它过期之后,下一次就得再登录一次(点一次 Get 即可)。

  • 令牌有效期间控件保持绿色且不写多余文字;「续期通道不可用」只在悬停说明里,

以及需要登录这类要你动手的状态下出现在第二行,不常驻警告;

  • 网络不可达 ≠ 令牌坏了:一个请求都没连上站点时,控件写的是

「网络不可达:连不上 madmodel 站点,Token 仍可用,稍后自动重试」(圆点转琥珀=未能校验),

不会把你引去重新登录;下一次成功运行会立刻清掉这句话;

  • 只完成一半也会说出来:令牌写进去了但模型配置没写成功时,状态是 partial

(「Token 已更新,但模型配置未同步:…」),而不是假装整体成功;

  • 登录窗口直接落在清华统一认证登录页

(id.tsinghua.edu.cn,带 ?/authLogin 回调,登录成功会跳回 madmodel)。

默认挂在左侧边栏底部:「设置」按钮上方;若设置上方已有其他插件的按钮

(如 Remote),则置于最顶部按钮的上方。Get/Auto 在左、计时器在右,

与 DSH 主题一致。连「设置」按钮都找不到时暂不显示,并持续重试。

安装

作为 DSH profile bundle(正式 npm 插件)安装,随 profile 声明同步:

dsh plugin --profile web add thu-tok-auto

然后重启 DSH Web(或对应 profile)使插件加载。也可手动在

~/.dsh/profiles/web/package.json 的 dependencies 与 dsh.profile.bundles

中加入 thu-tok-auto 后重新安装。

更新:

dsh plugin --profile web up thu-tok-auto

使用

1. 安装并重启后,侧边栏底部「设置」上方出现 [●] [Get] [Auto ✓] hh:mm 控件

(若 Remote 等插件已在设置上方,则排在其最上方;Auto 关闭时按钮显示为 Auto);

2. 点 Get —— 按下面的「获取阶梯」逐级续期:能自动续上就绿点亮起、token 已写入;

自动路径都刷不出新令牌时会打开登录窗口,登录完成后无需再点第二次(控件会先写

「等待登录」、再写「正在处理」),插件自己完成捕获→校验→写凭据→同步 Provider,

然后关掉它自己开的那个窗口;

3. 点 Auto 开启自动续期:按钮变绿、白字 Auto ✓(再次点击关闭恢复原样)。

免登录签发在 2026-09-29 被站点关掉了(无凭据调用返回 10001),所以现在必须先登录过一次:

手上有仍可用的令牌就直接复用;自动路径都刷不出新令牌时,手动点 Get 会打开清华统一认证登录页,

登录完成后自动捕获并继续。后台 Auto 永不弹窗:无人看管时它只会如实显示「需要登录」,

不会在旁边自己弹出窗口。拿到同一张令牌时不会显示成功,而是如实标成「刷新未生效」。

工作原理

获取阶梯(依次尝试)

层级 · 方式 · 说明

1 · GET /model-api/auth-login/check(用现有凭据) · 用已在凭据里的令牌直接换一枚新令牌

2 · SSO 重放 · 用保存的 cookie jar 走一遍统一认证链取 ticket;登录窗口捕获时也用它兜底(页面还没写 localStorage,cookie 已经能用了)

3 · 复用已保存 token · 仅当旧 token 仍被 /model-api/auth-login 校验通过

4 · 打开登录窗口 · 只在你手动点 Get 时;一次点击即完成全部后续(捕获→校验→写→同步→关窗)。后台 Auto 永不弹窗

5 · 比 exp 判成败 · 拿回同一张令牌(会话未变)不算刷新成功,状态标成「刷新未生效」而不是 ok

成功签发的 token 会同时写入:

  • DSH 凭据:credentials.set('MADMODEL_API_KEY', token)
  • DSH 模型配置:按 apiKeyEnv: MADMODEL_API_KEY,或 baseURL 指向 madmodel

(含本地转发 http://127.0.0.1:…/v1 的情形)找到目标 Provider;找不到则自动创建

llm-pi-ai.providers.madmodel(api: openai-completions)。写入走 DSH 的

settings.describe() + settings.update(),只合并目标的 apiKeyEnv 与 models,

不会把其他 Provider 复制成用户层覆盖,也不会抹掉同命名空间下的其他 Provider;

madmodel 这个键已被别的配置占用时宁可不写并报错,也不覆盖它。

模型列表跟着站点走

站点的模型会改名、下架、换档位(2026-09 就把 DeepSeek-V4-Flash-0731 换成了

DeepSeek-V4.1-Flash,旧名字现在请求直接返回"模型不存在")。插件不写死这份名单:

  • 每次 Get / Auto 签发后,从站点自己的前端包里读它正在用的模型列表

(站点没有模型列表接口,/v1/models 会落回 SPA),转成 provider 的 models

写进去;列表与现有配置一致时不写盘。结果缓存 6 小时,避免每次重复下载几 MB 的包。

  • 读不到时回退到代码内置的名单,功能不受影响。
  • 排除名单(EXCLUDED_MODEL_IDS):DeepSeek-V4-Flash-Vision-Exp(V4.1-Flash

已覆盖图片输入)与 DeepSeek-R1-W8A8。

  • 注意:既然名单跟着站点走,手动往 provider 里加的模型会在下一次签到时被同步覆盖;

要长期保留请加进代码里的名单。

  • contextWindow 统一写 1000000,取两个实测上限中较小的那个(2026-10-01 复测):

模型侧 1,048,576 prompt tokens 通过、再往上被拒(返回「服务器繁忙」);网关侧

client_max_body_size 8m,8,388,608 字节通过、8,388,609 被 413(折合英文约 134 万

token)——所以现在模型才是瓶颈。留约 4.8 万 token 给系统提示与工具定义。

(旧的 150000 来自 2026-10 之前那个 1 MiB 网关上限,已被站点抬高。)

时间语义(实测数据)

  • 令牌是 6 小时的 JWT(exp − iat == 6h,历史采样观察,并非站点保证)。

面板按本地时钟计算剩余寿命;若签发服务时钟比本地快约 9.6 分钟,显示值会

高估服务端的剩余寿命约 10 分钟。请保持系统时钟同步,并以服务端校验为准。

  • 面板的剩余时间直接取令牌自己的 exp(本地解码,不发请求),不再用「最近一次获取

时间 + 6h」估算:后者在「读回浏览器里那枚旧令牌」时会多报寿命——2026-10-01 实测到

令牌 14:06 签发、16:30 读回,面板按 16:30 + 6h 报,多出约 2.4 小时。

  • 每次拿到令牌后都向服务端核对一次(/model-api/auth-login),结果记进状态;服务端

明确拒绝(401/403,或 200 且 success:false)时面板按「已失效」显示,而不是继续显示 ok。

核对问不出结果时(连不上、答非所问)不写判定:状态是 partial

(「未能向服务端校验:判定未知」),而不是把网络问题写成"服务端不接受该令牌"。

  • 计时仍是本地量:now − 最近一次获取时间。
  • **Auto 间隔 20 分钟

…(truncated)

Rendered from the README published on npm. Formatted only, not edited.

Versions

Published on npm::11,最后更新 2026-11-01

Links

GitHub · Homepage · npm

Same category