面向 DSH 的清华 MadModel 接入:自动续期校园 token,按网络在校内直连与校外 WebVPN 之间切换,经本地回环转发模型请求并按模型排队。
安装
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:aaabrli/dsh-thu-automad
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
功能
| 能力 | 说明 |
|---|---|
| 自动续期 | 提前 1 小时用学号 + 统一认证口令重新登录,新 token 写回 TSINGHUA_API_KEY;剩余 30 分钟时状态药丸转琥珀色。 |
| 校内 / 校外 | 校内直连换票;校外走 统一认证 → WebVPN 会话 → 隧道内换票,请求随隧道 cookie 转发。 |
| 本地传输层 | provider 指向 127.0.0.1:43110/v1,按当前网络自动选择直连或隧道;SSE 边收边转。 |
| 并发排队 | 网关按模型限流,超出的请求在本地排队,429 冷却后重发同一个请求,不换模型、不打断对话。 |
| 失败策略 | 有序规则表:renew / retry / switch / ask / fail。 |
| 设置页与状态卡 | 概览、模型与并发、连接三个区块;状态药丸点开是剩余寿命、通道与续期,以及逐模型的并发槽位(在用/上限、排队、429 冷却倒计时)。 |
安装
dsh plugin --profile web add github:aaabrli/dsh-thu-automad
也可以在 DSH 的「插件 → 添加插件」里填本仓库地址。
[!IMPORTANT] 插件在 Host 侧运行,装完必须重启 DSH 才生效;更新时重跑同一条命令即可。
bundle 自带 provider 行(清华 DeepSeek → tsinghua,baseURL: http://127.0.0.1:43110/v1),无需手写;只有改端口时要同时改 transport.port 和这个 baseURL。
配置
默认即可用。需要调整时编辑 cordis.patch.yml 里的 config:
transport:
enabled: true
mode: auto # auto | direct | webvpn
port: 43110
keepaliveMs: 1200000
concurrency:
initial: 3
max: 3
perModel: # 网关按模型分别限流
qwen3.8-27b: 4
DeepSeek-R1-W8A8: 1
min: 1
growAfter: 4
queueLimit: 32
maxWaitMs: 0 # 0 = 不设排队上限
credentialRef、warnBeforeMs、refreshAheadMs、autoRenew、verifyAfterRenew、rules 等一般保持默认;各键含义写在 cordis.patch.yml 的注释里。
使用
- 设置 → 清华 MadModel,填学号与统一认证口令,点「立即续期」。
- 首次校外登录按提示完成二次验证;勾选「登记为可信设备」后,学校对这台设备的豁免约半年。
- 输入框下方药丸显示当前通道:
校园直连/WebVPN 隧道。
设置 → 清华 MadModel
├─ 概览 通道 / 令牌 / 续期 / 设备验证
├─ 模型与并发 在跑数 / 上限 / 排队 / 429 冷却
└─ 连接 本地端点 / 隧道会话 / 登录账号
工作方式
provider 行 ──> http://127.0.0.1:43110/v1 ──┬─ 校内:https://madmodel.cs.tsinghua.edu.cn/v1
(DSH) (本插件,仅回环) └─ 校外:https://webvpn.tsinghua.edu.cn/https/<hash>/v1
- 网络判定:
mode: auto时用未认证 GET 探测直连域名,返回应用页面即校内、返回 3xx 即校外;结论缓存 1 分钟。 - 隧道保活:WebVPN 会话空闲约 2 小时失效,默认每 20 分钟探活一次;失效则重跑登录链。
- 校外先登录:判定为隧道而本地没有会话 cookie 时,请求先等一次完整登录再发上游——没有会话的请求只会换回学校登录页,先发一次等于白跑一趟。
- 失会话重试:上游回登录跳转时重登一次并重发同一个已缓冲的请求。登录拿不出可用会话时,这一轮报成带修复提示的本地错误,不会把跳转透传给 DSH:相对
Location会被客户端按自己的回环 baseURL 解析,变成对127.0.0.1:43110/login的 404。 - 登录去重:并发与连续重试共用一次登录;失败后 15 秒内不再重登,成功后 5 秒内不重复登录,避免把一次网络抖动变成一串登录尝试。
并发与排队
网关按模型限制同一账号的在途 completion 数(实测值):
| 模型 | 并发上限 |
|---|---|
| DeepSeek-V4.1-Flash | 3 |
| qwen3.8-27b | 4 |
| DeepSeek-R1-W8A8 | 1 |
插件不超发,超出的请求按下面的规则处理:
- 每个模型维护自己的在途上限;超出的请求留在本地队列,不发给上游。
- 429 不抛给对话:该请求放回队列,该模型进入冷却(5s 起、翻倍、上限 120s,有
Retry-After就按它等),结束后重发同一个请求。 - 流式请求等待超过 20 秒后先回 SSE 注释行保活,槽位一到继续写同一条流。
- 队列上限 32 条;对话取消或客户端断开时立刻释放该请求的并发槽。
常见问题
排队会等到什么时候? 默认不设插件侧上限(maxWaitMs: 0),等到有槽位或你取消为止。真正的超时上限是 provider 行的 timeoutMs 与 streamIdleTimeoutMs(bundle 里都是 1 小时),想更早放弃就调小它们。
切到热点 / 换代理后第一轮就失败? 隧道会话与来源网络绑定,插件会重新判定网络、重登一次并重发。若登录链没走通,这一轮会明确报「school's gateway redirected the request … 请到 设置 → 清华 MadModel 点 立即续期」,而不是一个看不懂的 404 或「模型不可用」。到设置页看一眼登录结果(状态卡与续期结果会列出失败码),点「立即续期」后再发消息即可。
模型并发被占满时续期会失败吗? 不会。续期后的校验探针遇到 429 会先重试两次;仍然忙就保留这次续期结果,只在结果里标注「未先行校验」,把排队交给真实请求自己走。429 是网关的排队信号,不是对这张 token 的判断。
状态卡显示「本地端口未监听」? 端口被占用,传输层没起来;换端口时同步改 provider 的 baseURL。
隐私与安全
[!WARNING] 口令、token 与隧道 cookie 存在
$DSH_HOME/.credentials.yaml,明文 YAML;本地传输层不做鉴权,只监听127.0.0.1。
同主机上能访问 43110 端口的程序都可以借用你的 token。不能接受这个取舍,就不要在该 profile 里配置口令。
已知限制
- 二次验证需要人工完成一次,之后依赖学校对可信设备的豁免。
- 隧道空闲约 2 小时失效,
keepaliveMs不要设得比它长。 - 模型能力、工具调用兼容性与上游协议细节沿用 madmodel-proxy,不在本插件范围内。
开发
npm install --no-save --legacy-peer-deps esbuild tsx
node build.mjs # 生成 lib/index.js(Host)与 lib/client.js(Web)
node node_modules/tsx/dist/cli.mjs checks/host-smoke.ts
node node_modules/tsx/dist/cli.mjs checks/policy-smoke.ts
node node_modules/tsx/dist/cli.mjs checks/client-smoke.ts
node node_modules/tsx/dist/cli.mjs checks/transport-smoke.ts
本地调试时用 profile 的 link: 依赖指向本目录,改完重启 DSH。
反馈
遇到问题请开 Issue。贴日志前请删掉 token、cookie 与学号。
致谢
- aaabrli —— 原始
dsh-thu-automad(v0.1.0)的作者;认证链、失败策略与设置页的基础来自这里。 - madmodel-proxy —— 认证链、WebVPN 隧道前缀与 cookie 处理的知识来源(
vendor/为其字节副本)。 - thu-tok-auto —— 直连 SSO 路径的实测参数与 NO_PROGRESS 判定。
许可
MIT,见 package.json。
链接
同类插件
Ebony-Vinyl/dsh-our-free-model★ 67530
为 dsh 接入免费模型车道(含 DeepSeek V4.1 Flash、Kimi K3 等),无需登录、注册或填写 API Key,并提供本地 OpenAI 兼容网关、降级路由与用量看板。
dingminhua/dsh-connect-workbuddy★ 1386
将本机登录的 WorkBuddy 模型(国内版与国际版)接入 DSH,每次刷新按上游目录读取每个模型的积分倍率,支持逐模型图片输入开关、带自动换号的账号池、手动每日签到,以及卡片与输入框里的只读积分胶囊读数。
Alice-Marx/dsh-model-router★ 957
为 DeepSeek Harness 规划有依赖的工作包,将其分配给已配置的模型 API 或支持的厂商 CLI,并提供费用预览。
V1ki/dsh-plugin-subscriptions★ 579
把 ChatGPT(Codex)、Claude、Grok 订阅当作 DeepSeek Harness 的 LLM 提供方:设置页登录、模型目录、用量展示,以及 image_generate、video_generate 与 x_search 工具。
XDTrees/dsh-workbuddy-xdpool★ 481
把本机 WorkBuddy 桌面 App 登录过的所有账号自动并入 DSH 模型池:多账号轮换自动容错、实时积分,模型目录按模型标注积分倍率与限时免费 / 夜间折扣。
XDTrees/dsh-xdpool★ 481
把本机 WorkBuddy 桌面 App 登录过的所有账号自动并入 DSH 模型池:多账号轮换自动容错、429 冷却、实时积分,模型目录按模型标注积分倍率与限时免费 / 夜间折扣,扫码登录 13 家厂商,聚合免费额度渠道。账号重启不丢。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。