Repository navigation
Releases: KERBALMans/dsh-modpack
Release list
dsh-modpack v0.9.1
这是什么
dsh-modpack 是 DeepSeek Harness 的插件整合包管理器。
打个比方:玩《我的世界》时,别人给你一个整合包(modpack),你导入进去,几十个模组一次性装好、配置好、排好顺序,不用一个个去下。这个插件就是把这件事搬到 DeepSeek Harness 上——把你自己机器上已经调好的那套插件,打包成一个文件发给朋友,他导入就还原成和你一样的插件环境。
一句话:勾选 → 打包 → 发文件 → 对方一键装回。
这一版(0.9.1)修了什么
一句话:Windows 上跑测试会失败,但插件本身在 Windows 上一直是好的。 修的是测试,不是功能。
第一次把仓库推上去,GitHub Actions 给了这么一张成绩单——Linux 两个绿,Windows 两个红:
✅ CI / node 20 on ubuntu-latest
✅ CI / node 22 on ubuntu-latest
❌ CI / node 20 on windows-latest
❌ CI / node 22 on windows-latest
红的那条日志里只有一句 Process completed with exit code 1.,看不到是哪条断言挂的。本地复现之后才看清:check-signals.mjs 在抱怨
FAIL: const AUTO_RULES = [ has no closing bracket in column 0
——可那个方括号明明在,就在第 0 列,好好的。
真正的原因是行尾。 Git 有个设置叫 core.autocrlf,Git for Windows 安装时会推荐你打开它,作用是把仓库里的 LF 换行在检出时转成 Windows 的 CRLF。于是同一个 commit,Linux 上跑出来是 LF,Windows 上跑出来是 CRLF。
而所有检查脚本都是这么干的:在源码里找 \n 开头的标记,切出一段,再用 /\n[\]}]\n/ 找这段的结尾。CRLF 下 ] 后面跟的是 \r,那个正则永远匹配不上。开头标记反而全都匹配——因为 \r\n 里确实含一个 \n。所以只有结尾扫描挂掉,报出来就是「括号没闭合」。
变异脚本(故意改坏源码、看测试会不会红的那些)中的一部分也没能幸免,只不过更安静:它们用多行文本去匹配源码,CRLF 下匹配 0 次,脚本把这种情况记成「模式不存在」,然后当作变异存活——等于把 7 个真实的守卫报成没验证过。
修法是两层,因为任意一层单独都有洞
.gitattributes钉住eol=lf:任何人 clone 下来就是 LF。实测:用-c core.autocrlf=true克隆,index.js的 CRLF 对数量从 3703 变成 0。- 脚本读源码时自己归一化(
scripts/source-text.mjs):因为第一层只管 git 产出的东西。你从 GitHub 下 ZIP、在 Windows 上解包 tarball、或者编辑器手滑改了行尾,.gitattributes都管不着。变异脚本则保留「磁盘上的原始文本」和「归一化后的文本」两份,还原时写回原始的那份——跑测试不会顺手改掉你的行尾。
还加了什么
scripts/check-eol.mjs:真的把整个插件复制一份、把所有源码转成 CRLF、把检查和变异脚本跑一遍。跑不绿就失败。顺带断言.gitattributes那条*规则还在——文件被删时报的是「断言失败」,不是检查器自己的ENOENT堆栈。scripts/mutate-eol.mjs:2 个变异,都验证过能被抓住。其中「把归一化改成空操作」这个尤其值得留着——那时.gitattributes还在,只有真跑 CRLF 沙箱才抓得到,而它复现出的报错和线上 CI 一字不差。- CI 会先打印这次检出拿到的是什么行尾:以后 Windows 再红,从日志一眼就能看出是不是同一类问题,不用再找台 Windows 机器复现。
这一版包含 0.9.0 的全部内容,下面继续。
0.9.0 做了什么
这是一个面向未来的适配版本,核心是三件事:
1. 两个半边之间加了版本握手
这个插件由两个文件组成:跑在 Node 里的宿主半边(index.js)和跑在浏览器里的客户端半边(client.js)。它们从两个不同的地方加载——宿主半边在插件被应用时读取,客户端半边由浏览器去取。
问题就出在这儿:升级之后,浏览器很可能还在用缓存里的旧页面,而宿主半边已经是新的了。这种组合下,你看到的每一个症状——「点了没反应」「导出的文件是空的」「按钮转圈不动」——看起来都像插件有 bug,其实只是两代代码在互相说话。
0.9.0 在两个文件里各写了一个 API_VERSION,加载时比一次:
- 宿主通过
GET /api/dsh-modpack/diag报出自己的号; - 页面拿自己的号去比;
- 不一样就显示一句话,直接告诉你怎么办:按 Ctrl+R 刷新;刷新还不行,就去插件页把本插件关掉再打开一次。
这里故意没有用插件版本号做这件事。插件版本号会因为改文档、改 CSS 而变,而旧页面只在接口形状变了的时候才真的危险。用一个只在这时候才动的数字,才不会动不动就误报。
2. 页面壳换了形状也不会把整个设置页带崩
window.__ModuleLoader__、ctx.slots.inject、插槽键名(settings.section)——这些都是 Harness 的实现细节,不是这个插件能规定的契约。
以前的写法是:拿不到就抛错。而这是在模块顶层抛的,等于整个设置页跟着一起白屏。
现在:加载器不在就不挂载(宿主半边照常工作),某个插槽键改名就只少一个标签页并在控制台说一句,另一个座位不受影响。一个名字不认识,代价应该是一个标签页,不应该是整个插件。
3. 宿主没有 ctx.inject 时不再静默失效
whenService 原来无条件调用 ctx.inject。在比它更老的 Harness 上,这个调用会在 apply 里抛出去,结果 HTTP 路由和三个智能体工具一个都没注册——而插件看起来还是"加载成功"的样子。
现在:没有 ctx.inject 就退回直接读服务,不比它替代的行为更差。
它到底能干什么
- 插件清单:自动读当前 profile 的
package.json与cordis.patch.yml,列出全部已安装插件(名称、版本、来源、启用状态、类型) - 筛选搜索:按名称、模块名、描述实时搜;按已启用 / 已禁用 / 本地链接 / 官方 / 可移除筛
- 分类树:自己命名的可嵌套分类,点分类即按其子树过滤,可整类勾选、批量归类;分类跟着整合包一起走
- 自动分类:一键按 31 条有序规则归类——作者声明的
keywords最优先,其次插件自己注册的简介、包里的 README,最后才是名字。先预览再应用,每行标注来源 - 四档可选证据:联网查阅 / AI 综合判断 / 附带源码 / 作用关系推理。默认全关,你点哪档它才走哪档
- 勾选打包:全选 / 反选 / 仅选已启用 / 仅选可分享,导出
.dshmodpack.json - 导入安装:选文件 → 预览要装什么 → 确认 → 一键装
- 分享引导:导出后直接给你一段能一键复制、发给对方智能体的话
- 可选锁定版本:默认按版本范围装(更耐下架),勾上就装精确版本(更可复现)
- 三个智能体工具:
modpack_list/modpack_export/modpack_apply,modpack_apply默认只预演,要显式dryRun: false才真装
兼容性
- DSH
>= 0.2.0-rc.1(开发验证于0.2.1-rc.3) - Node
>= 20 - Windows / macOS / Linux
- 客户端表面:Web
关于"未来版本":这个插件不比对版本号,而是探测 pluginManager 上每个方法在不在。少了 installBundle 就禁用安装按钮并说明原因;少了 setBundleEnabled 就只装不启;少了 waitForInstall 就没有进度条但照样装完。某个方法被拿掉,只失去那一项功能。
安全
- 宿主半边只注册一个 HTTP 前缀路由
/api/dsh-modpack,每个请求先过connection.admit(),只有本机回环可用 - 分类树只写自己目录下的
storages/dsh-modpack/categories.json,不碰任何插件文件 - 导入全部走
pluginManager官方接口,不会自己改写package.json、cordis.patch.yml或node_modules - 出网只有一个入口且默认关闭:勾了「联网查阅」才去 npm / GitHub 请求公开的包元数据,发出去的只有插件名
- 除上述之外没有任何出网请求、没有遥测
安装
dsh plugin --profile desktop add ./dsh-modpack-0.9.1.tgz装完在 设置 → 插件整合包 里。
⚠️ 本插件没有发布到 npm。dsh-modpack这个名字在 npm 上属于另一个作者、另一个项目。请只从本仓库的 Release 下载 tgz,不要在插件管理器里直接填dsh-modpack。
测试
15 个检查套件 + 8 个变异套件(84 个变异),全部通过。CI 在 Node 20/22 × Linux/Windows 上跑全套。
变异测试的意思是:故意把源码改坏,然后看测试会不会红。不会红的测试不算测试。
更新日志
完整改动见 CHANGELOG.md。
dsh-modpack v0.9.0
这是什么
dsh-modpack 是 DeepSeek Harness 的插件整合包管理器。
打个比方:玩《我的世界》时,别人给你一个整合包(modpack),你导入进去,几十个模组一次性装好、配置好、排好顺序,不用一个个去下。这个插件就是把这件事搬到 DeepSeek Harness 上——把你自己机器上已经调好的那套插件,打包成一个文件发给朋友,他导入就还原成和你一样的插件环境。
一句话:勾选 → 打包 → 发文件 → 对方一键装回。
这一版(0.9.0)做了什么
这是一个面向未来的适配版本,核心是三件事:
1. 两个半边之间加了版本握手
这个插件由两个文件组成:跑在 Node 里的宿主半边(index.js)和跑在浏览器里的客户端半边(client.js)。它们从两个不同的地方加载——宿主半边在插件被应用时读取,客户端半边由浏览器去取。
问题就出在这儿:升级之后,浏览器很可能还在用缓存里的旧页面,而宿主半边已经是新的了。这种组合下,你看到的每一个症状——「点了没反应」「导出的文件是空的」「按钮转圈不动」——看起来都像插件有 bug,其实只是两代代码在互相说话。
0.9.0 在两个文件里各写了一个 API_VERSION,加载时比一次:
- 宿主通过
GET /api/dsh-modpack/diag报出自己的号; - 页面拿自己的号去比;
- 不一样就显示一句话,直接告诉你怎么办:按 Ctrl+R 刷新;刷新还不行,就去插件页把本插件关掉再打开一次。
这里故意没有用插件版本号做这件事。插件版本号会因为改文档、改 CSS 而变,而旧页面只在接口形状变了的时候才真的危险。用一个只在这时候才动的数字,才不会动不动就误报。
2. 页面壳换了形状也不会把整个设置页带崩
window.__ModuleLoader__、ctx.slots.inject、插槽键名(settings.section)——这些都是 Harness 的实现细节,不是这个插件能规定的契约。
以前的写法是:拿不到就抛错。而这是在模块顶层抛的,等于整个设置页跟着一起白屏。
现在:加载器不在就不挂载(宿主半边照常工作),某个插槽键改名就只少一个标签页并在控制台说一句,另一个座位不受影响。一个名字不认识,代价应该是一个标签页,不应该是整个插件。
3. 宿主没有 ctx.inject 时不再静默失效
whenService 原来无条件调用 ctx.inject。在比它更老的 Harness 上,这个调用会在 apply 里抛出去,结果 HTTP 路由和三个智能体工具一个都没注册——而插件看起来还是"加载成功"的样子。
现在:没有 ctx.inject 就退回直接读服务,不比它替代的行为更差。
它到底能干什么
- 插件清单:自动读当前 profile 的
package.json与cordis.patch.yml,列出全部已安装插件(名称、版本、来源、启用状态、类型) - 筛选搜索:按名称、模块名、描述实时搜;按已启用 / 已禁用 / 本地链接 / 官方 / 可移除筛
- 分类树:自己命名的可嵌套分类,点分类即按其子树过滤,可整类勾选、批量归类;分类跟着整合包一起走
- 自动分类:一键按 31 条有序规则归类——作者声明的
keywords最优先,其次插件自己注册的简介、包里的 README,最后才是名字。先预览再应用,每行标注来源 - 四档可选证据:联网查阅 / AI 综合判断 / 附带源码 / 作用关系推理。默认全关,你点哪档它才走哪档
- 勾选打包:全选 / 反选 / 仅选已启用 / 仅选可分享,导出
.dshmodpack.json - 导入安装:选文件 → 预览要装什么 → 确认 → 一键装
- 分享引导:导出后直接给你一段能一键复制、发给对方智能体的话
- 可选锁定版本:默认按版本范围装(更耐下架),勾上就装精确版本(更可复现)
- 三个智能体工具:
modpack_list/modpack_export/modpack_apply,modpack_apply默认只预演,要显式dryRun: false才真装
兼容性
- DSH
>= 0.2.0-rc.1(开发验证于0.2.1-rc.3) - Node
>= 20 - Windows / macOS / Linux
- 客户端表面:Web
关于"未来版本":这个插件不比对版本号,而是探测 pluginManager 上每个方法在不在。少了 installBundle 就禁用安装按钮并说明原因;少了 setBundleEnabled 就只装不启;少了 waitForInstall 就没有进度条但照样装完。某个方法被拿掉,只失去那一项功能。
安全
- 宿主半边只注册一个 HTTP 前缀路由
/api/dsh-modpack,每个请求先过connection.admit(),只有本机回环可用 - 分类树只写自己目录下的
storages/dsh-modpack/categories.json,不碰任何插件文件 - 导入全部走
pluginManager官方接口,不会自己改写package.json、cordis.patch.yml或node_modules - 出网只有一个入口且默认关闭:勾了「联网查阅」才去 npm / GitHub 请求公开的包元数据,发出去的只有插件名
- 除上述之外没有任何出网请求、没有遥测
安装
dsh plugin --profile desktop add ./dsh-modpack-0.9.0.tgz