dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
走头歌(EduCoder)平台 JSON API 完成作业,无浏览器自动化。educoder_sweep 扫描所有课程中仍有未通过关卡的作业——已完成的作业直接跳过、一个关卡都不读,因此全量扫描不消耗模型 token——并可一次做完;选择题同样零 token,因为平台会在任意一次提交的响应里回吐标准答案;代码题由模型生成,以 evaluate:0 上传后每关只触发一次评测,再按平台返回的报错重试。三个工具:educoder_sweep、educoder_homework、educoder_account。
头歌(EduCoder)作业自动化 — 一个 DSH 插件:全量扫描账号里所有未完成的作业,然后一次做完。
没有浏览器自动化,没有截图识别,没有 OCR:每一步都是平台自己的 JSON 接口。
这是本插件最核心的设计,分三层:
standard_answer 都是 null,包括一份 172 题的期末复习)。但平台会在任意一次提交的
响应里回吐每道题的标准答案。所以做法是:提交一次探针答案 → 从响应收割答案键 →
再提交正确答案。全程不需要模型,也不需要猜。| 工具 | 作用 |
|---|---|
educoder_sweep | 推荐入口。 扫描整个账号(或指定一门课),找出所有还有未通过关卡的作业。mode=scan(默认)只读不提交、零 token;mode=solve 真正做完,选择题零 token、代码题调模型。 |
educoder_homework | 单份作业。参数 url(作业链接或 homework_common_id);mode=solve(默认)真正做完,mode=survey 只巡检不提交。 |
educoder_account | 检查账号连接状态并列出课程。可选参数 url:传了会真读一次该关卡,那才是会话有效的证据(只列课程不算)。登录/权限报错时用它定位问题。 |
educoder_homework 的 url 接受这几种写法:
https://www.educoder.net/tasks/AGUY4O7A/4197532/op7hwrazem5u ← 浏览器里直接复制的
https://www.educoder.net/tasks/4197532/op7hwrazem5u
https://www.educoder.net/tasks/op7hwrazem5u
https://www.educoder.net/tasks/AGUY4O7A/4197532 ← 只有作业、没有具体关卡
4197532 ← 纯 homework_common_id
日常用法就是一句:
你:还有哪些作业没做? → educoder_sweep mode=scan (零 token)
你:都做了吧 → educoder_sweep mode=solve
写在 bundle 的 cordis.patch.yml 里,也可以在插件设置界面改:
| 键 | 默认 | 说明 |
|---|---|---|
login / password | 空 | 头歌账号。首次登录后只复用会话 cookie,密码不会出现在对话里。 |
sessionFile | ~/.educoder/session.json | 会话缓存路径,与 educoder-lab CLI 共享:那边登录过,这边直接可用。 |
provider / model | 空 | 生成答案用的模型;留空用当前会话正在用的模型。 |
maxAttempts | 3 | 每道代码题最多重试几次。 |
maxTokens | 8000 | 单次生成上限。 |
gradeTimeoutSec | 180 | 单次评测最长等待。 |
pollIntervalSec | 3 | 轮询评测结果的间隔。 |
challengeLimit | 0 | 单份作业里 0 = 一次做完所有未通过关卡。 |
homeworkLimit | 0 | 单次全量扫描最多处理几份作业;0 = 不限。 |
toolTimeoutMinutes | 45 | 工具整体超时。 |
这些行为来自对平台的实测,不是猜的:
X-EDU-Type/Timestamp/Signature,签名是
md5(base64("method=<M>&ak=<AK>&sk=<SK>&time=<epoch-ms>"))。
AK/SK 是头歌自己前端 bundle 里的公开客户端常量,不是用户密钥。prev_game/next_game 走;
而 shixun_exec.json 返回的是最后访问的关卡,不是第一关没过的。
所以先沿 prev_game 回退到头,再向前走;并且通过一关之后重新读它,
因为 next_game 在上一关通过前一直是 null。evaluate: 0,
全部文件传完再触发一次 game_build.json —— 每个文件触发一次会评测到半成品工作区,白烧评测配额。test_sets 里有 result: null 时表示评测还在跑,看到 test_sets 就当作结论是错的。
判定要等 game.evaluate_count 真的涨了(确认新一轮跑起来了),再等两次轮询结果一致;
game.status == 2 直接算通过。—(U+2014),不是合法代码。答案里还留着它就直接本地重试,
不浪费一次评测。{"status":401} 表达「请登录」,
而 HTTP 状态码是 200,只看状态码永远发现不了。检测到就自动用配置的账号重登一次再重试,
且这发生在任何写入之前,不会重复提交。/courses.json 不是鉴权接口:没有会话也返回课程列表,所以它不能用来验证凭据;
只有读一次关卡才算证据。插件的会话校验因此放在第一次关卡读取上。包名 dsh-educoder,bundle 行 id 是 educoder。
# npm(推荐,预构建安装还能跳过构建授权)
# target: dsh-educoder
# 从 GitHub 装:
# target: github:isheng-eqi/dsh-educoder
# 从本地目录装:
# target: <本目录绝对路径>
三种方式装的是同一份代码。npm 上的是 dsh-educoder,
发布包只含 12 个文件(index.js、lib/、tests/、locale/、icon.svg、
cordis.patch.yml、README、LICENSE),不含 node_modules。
装好后 ~/.dsh/profiles/<profile>/cordis.patch.yml 里会出现 educoder 这一行,
在它的 config 下填 login / password 即可 —— config 是热应用的,不用重启。
配置改完后可以直接自检:
educoder_account url: <你的作业链接>
它会真读一次该关卡;能读到就说明会话有效(只列课程不算证据,见下)。
只想看不提交就用 educoder_homework 的 mode: "survey"。
对方只需要有 DSH 和一台能联网的机器,三步:
plugin_manager,action: install_bundle,
target: dsh-educoder(npm)或 target: github:isheng-eqi/dsh-educoder(GitHub)。
两者都是公开的,不需要任何凭据。包名是新的,首次加载直接生效,不用重启。cordis.patch.yml。
填的是使用者自己的头歌账号;插件驱动的就是配置里那个账号。educoder_sweep mode=scan,零 token),
或「都做了吧」(mode=solve)。不需要 Python、不需要浏览器扩展、不需要任何第三方密钥:
node_modules,唯一的外部依赖 @deepseek-ai/schemastery
由 DSH 安装本身提供 —— profile 的 pnpm-workspace.yaml 固定写着 nodeLinker: hoisted,
依赖是扁平摊在 <profile>/node_modules 里的,任何插件都能沿目录向上解析到。
(已实测:把公开发布版 clone 到一个全新的空目录、再按 pnpm 的布局放好,
import('./index.js') 直接成功,schemastery 从 profile 解析到。)~/.educoder/session.json(0600),只有首次需要账号密码。⚠️ 它会真实提交到平台并消耗评测次数,驱动的是配置里那个账号——给别人之前请让对方知道这一点。
/courses.json 不需要登录也返回数据,所以「能列出课程」不能证明凭据有效;
只有读一次关卡才是证据。插件的会话校验因此放在第一次关卡读取上。{"status":401,...}),
只看 HTTP 状态码发现不了。插件检测到这个 code 就会自动用配置的账号重登一次再重试,
而且这发生在任何写入之前,不会重复提交。DSH 按包名缓存已加载的插件模块,同一个进程内不会重新 import 同名包 ——
实测禁用/启用、换目录、甚至 remove_bundle + install_bundle 都拿不到新的 JS
(栈里的路径会一直指向第一次加载的位置)。
所以:
index.js / lib/*.js → 必须重启 dsh web;config(账号密码、重试次数等)→ 不用重启,profile patch 由 HMR 热应用。同理,如果插件第一次加载就报错,后面的修改不会自愈,重启即可。
想不重启就换代码,只有改包名一条路(会变成另一个包)—— 这也是本包从
dsh-plugin-educoder 改名成 dsh-educoder 的原因之一,顺带更贴合生态命名习惯。
两个套件都不联网、不消耗评测次数:
cd "$DSH_PROFILE_DIR" # 让 @deepseek-ai/dsh-tools 能被解析
node <本目录>/tests/smoke.test.mjs
node <本目录>/tests/solve-loop.test.mjs
smoke.test.mjs(63 项):工具注册走的是 DSH 真实的
assertSupportedJsonSchema(第一版就是死在这上面);另外覆盖传输层
(body 401 / -102 / Set-Cookie 取会话)、URL 解析、签名、以及在 mock 平台上的
整份作业遍历与会话恢复。solve-loop.test.mjs(65 项):用脚本化的模型 + mock 平台把解题循环钉死 ——
上传与评测的报文形状、"多文件只触发一次评测"、占位符答案不浪费评测次数、
重试时反馈里带了什么、重试耗尽、缺环境时拒绝半提交、中途失败保留已完成结果、
输出被 maxTokens 截断时的提示、选择题零 token 收割(并断言全程不碰模型)、
以及 scan 绝不提交。mode=solve 会真实提交到平台并消耗评测次数;不确定时先用 mode=survey 巡检。0600 权限写入,和密码一样只落在本机。AK/SK 是平台公开常量;这里没有、也不需要任何第三方密钥。MIT。这是一个非官方自动化客户端,请在自己的账号上、按头歌平台条款使用。