yibinthesis-dsh
Verifiedyibinthesis-dsh · v0.1.1 · MIT · Web UI
YibinThesis — 宜宾学院本科毕业材料(毕业论文/开题报告/文献综述)的 LaTeX 排版工具,作为 DeepSeek Harness 原生插件:注册 yibinthesis_* 原生工具(项目摘要 / 工具链检查 / 脚手架 / PDF 与 DOCX 构建 / 格式检查 / 清理)、按需加载的 yibinthesis 技能,以及一个 Web GUI 工具链状态与构建面板。
Install
dsh plugin add yibinthesis-dsh Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Tags
Creators
Readme
yibinthesis-dsh
把 YibinThesis(宜宾学院本科毕业材料的 LaTeX 排版工具)接入
DeepSeek Harness,作为原生插件:一组 yibinthesis_* 原生工具、一份按需加载的技能,
以及一个 Web GUI 工具链状态面板。
本工具是非官方实现。学校、学院或专业的新通知优先于本工具;提交前仍需由指导教师或所在学院复核。
功能范围
上游 YibinThesis 由 Python CLI、PowerShell 构建器与 LaTeX 文档类组成,在终端中可用,
但助手调用时需先确定:项目位置、文档类型、缺失的排版工具,以及失败源于配置还是环境。
本插件将这些判断转化为结构化调用:
| 工具 | 用途 | 只读 |
|---|---|---|
yibinthesis_probe |
项目摘要:配置、入口与文档类型、封面元数据、章节与汉字数、交付路径 | ✅ |
yibinthesis_doctor |
工具链就绪度,并指出缺项与补法 | ✅ |
yibinthesis_new |
新建项目骨架(支持 dry_run 预览) |
❌ |
yibinthesis_build |
构建 PDF / DOCX | ❌ |
yibinthesis_check |
结构与格式检查 | ❌ |
yibinthesis_clean |
清理构建产物 | ❌ |
另含渐进披露技能 yibinthesis,以及一个状态面板(除「设置产物输出名称」外只读)。
状态面板
入口:会话右侧栏的「论文工具」标签页,与「工作区文件 / 上下文 / 新建终端 / 浏览器」同列。
另有备用入口:插件 → 已安装 → yibinthesis-dsh → 该行的「配置」(plugins.row.config)。
位置选型依据
面板承载的是当前会话的论文项目,属于会话级 UI,因此注册到会话右侧栏, 而不是与「插件 / 技能中心」并列的应用级侧栏。注册由三处配对完成,共用同一 id:
| 作用 | 注册点 |
|---|---|
| 声明标签条目(含图标;缺此项标签不出现) | ctx.inject(['sidebarRightTabs']) → sidebarRightTabs.register({ id, kind, title, guide }) |
| 标签正文 | 槽位 sidebar.right.pane.tab,key = id |
| 标签标题头 | 槽位 sidebar.right.pane.tab.title,key = id |
该配对由 tests/contract.test.mjs 的「客户端半:必须注册会话右侧栏标签」与
tests/client-render.test.mjs(真渲染 + 逐项内容断言 + 抛错可见性)机械保证。
呈现内容
项目状态:题目 / 作者 / 学号 / 年级 / 院系 / 导师、文档类型与学科、章节文件数、 正文字数;论文文件清单(按用途分「正文 / 资源 / 数据 / 文档」标签页,正文每章附汉字数, 点击即在右侧栏预览);两份交付物的存在性、体积与生成时间,已生成者可直接打开。
一个会话可承载多篇文档。 毕业论文、开题报告、文献综述对应
yibinthesis_new的三种documentType,各为独立项目,因此面板维护的是项目列表(点条目切换,×从列表移除, 不删除磁盘文件)。列表按会话持久保存,初始为空——defaultProjectDir在本部署 刻意留空,以免每个新会话都指向同一项目。助手可用yibinthesis_new建项目, 或用任一工具的project_dir参数指定路径。文件分类的必要性。 实测样本含 148 个文件:
latex/assets/52(插图与中间件)、图表资源/44、plan/26、tmp/10,而正文仅 13 个.tex。合并展示时正文会被资源淹没。 分类判据为用途而非扩展名,实现见categorizeProjectFile(); 「资源」页按目录聚合呈现,不逐条展开。工具链就绪度:Tectonic / Biber 版本 / Pandoc / Python / python-docx / Pillow 逐项状态, 附
exit 0/2与可按需展开的原始输出。生效配置:
templateRoot、cliRoot、toolchainDirs、defaultProjectDir。
路由与写面
面板不触发构建:经 Web 路由调用编译会显著扩大权限面(任何能访问该端口的页面均可让宿主写盘)。
构建与脚手架一律由助手经 yibinthesis_build / yibinthesis_new 发起,受正常的工具审批与取消链路约束。
桥暴露 5 条路由,其中仅一条可写:
| 路由 | 方法 | 作用 |
|---|---|---|
/state |
GET | 插件配置与项目概况 |
/probe |
GET | 结构化项目摘要(经 Python 适配器) |
/deliverables |
GET | 交付物存在性 / 体积 / 时间 |
/deliverables |
POST | 设置产物输出名称(唯一写操作,由用户点击触发) |
/files |
GET | 项目文件清单(跳过构建产物目录) |
/doctor |
GET | 工具链就绪度 |
写路由必须显式登记于 BRIDGE_WRITE_ROUTES。tests/bridge.test.mjs 断言「除白名单外一律只读」;
tests/client-render.test.mjs 断言客户端写调用恰好一处、必须挂在点击处理器上、且不得在 effect 中自动执行。
新增写操作会被这两条测试强制要求同步更新白名单。
设计取舍:薄桥,不重写
上游的分工是「PowerShell 与 Python 管排版」。本插件不将 53 KB 的 build.ps1
与 280 KB 的 Word 模块移植到 JS——那只会引入回归风险。插件职责限于探测、校验、编排、结构化:
DSH 工具调用
└─ Node(本包)
├─ 工具链探测(env → .tools/ → PATH)+ 子进程 PATH 组合
├─ 结构读取 ──→ adapter/yibinthesis_probe.py(只读,输出唯一 JSON)
└─ 构建编排 ──→ vendor/yibinthesis/build.ps1(PDF/Word/check/clean/doctor)
两条硬规则:
- 不假装成功。 缺工具就报
ok:false+kind:'missing-toolchain'+ 可操作提示, 绝不产出「部分成功」的构建结论。 - 失败给
kind,不给裸异常。 所有工具都不抛,失败变成{ ok:false, kind, message, hints },让调用方知道该补环境还是改配置。
安装
见 docs/INSTALL.md。要点:
# 1) 装进一个 DSH profile(用 npm 包名,或本地路径)
cd $env:USERPROFILE\.dsh\profiles\desktop
pnpm add yibinthesis-dsh
# 2) 在 profile 的 package.json 里把包名加进 dsh.profile.bundles
# 3) 重载 profile(或重启 DSH)
只想用模板运行时、不装插件也可以:直接用上游 YibinThesis 仓库的 build.ps1。
与上游的兼容性
本插件随包携带 YibinThesis 模板运行时的发布快照(见 vendor/yibinthesis/)。
该快照为 commit c453a26,与上游 lib/ 下 33 个共有文件逐字节一致。
联调期间曾在上游发现两处导致 DOCX 链路失败的缺陷。两处均已由上游修复并并入本快照, 本插件不代修上游排版逻辑,此处记录仅用于说明快照版本与验证依据。
已修复:word_core 的私有 OOXML 函数未绑定
lib/word_oxml.py 通过 bind_core(core) 将自身名字并入 word_core;lib/word_core.py
的 _bind_oxml_module() 再将合并后的私有名字注回 word_core。原实现在注回时排除了
_build_front_matter、_build_cover_page、_build_originality_page、_build_authorization_page
四个名字,而它们只在 word_oxml.py 中定义,word_core.py 中并不存在。
因此 postprocess_docx() 以裸名调用时触发 NameError。
上游修复:注回条件改为 name.startswith("_"),即绑定全部私有 OOXML 函数。
已修复:分节标记的注入点与消费点不同源
原实现在 word_core.py 的论文构建路径上注入 SECTION_REVIEW_REFERENCES 与
SECTION_REVIEW_TAIL 两个内部标记,而清理它们的代码位于 word_profiles.py 的
_postprocess_review_docx(),只服务于文献综述。两者不同源,导致
word_core.py 的「后处理标记未清理」守卫必然抛错。
上游修复:将三处标记注入移入 word_profiles.py 的非论文构建路径,与消费点同处一文件。
本插件的验证结论
| 链路 | 结果 |
|---|---|
✅ 通过(示例项目产出 163.2 KB,%PDF-1.5) |
|
| DOCX | ✅ 通过(示例项目产出 62.8 KB,PK 魔数;word/document.xml 中两个内部标记均已清理) |
| 模板回归 | ✅ 通过(yibinthesis_check 的冒烟夹具) |
若使用自定义 templateRoot 指向较旧的上游检出,上述缺陷可能仍然存在;
yibinthesis_build 检测到相应症状时会返回 kind: 'upstream-word-defect' 并附诊断。
工具链:本包不分发排版二进制
上游 .tools/ 下的 Tectonic + Biber + Pandoc 合计约 312 MB(biber.exe 31.7 MB、
pandoc.exe 231.1 MB、tectonic.exe 49.6 MB),不适合进 npm 包。
本包改为按三层优先级探测:
- 环境变量
YIBINTHESIS_TECTONIC/YIBINTHESIS_BIBER/YIBINTHESIS_PANDOC/YIBINTHESIS_PYTHON/YIBINTHESIS_LATEXMK/YIBINTHESIS_XELATEX - 插件与项目的
.tools/(约定:biber-2.17/biber.exe、pandoc-3.9.0.2/pandoc.exe、tectonic/tectonic.exe)、以及本机已知缓存路径 PATH
Biber 必须是 2.17:Tectonic 0.16.9 的 BCF 3.8 工作流与 2.21 不兼容。
先跑 yibinthesis_doctor 看缺什么。
配置
在 profile 补丁里按行 id 覆盖(cordis.patch.yml):
- id: yibinthesis
name: yibinthesis-dsh
config:
templateRoot: 'D:\src\YibinThesis' # 想跟随上游更新时指向它;默认用随包副本
cliRoot: 'D:\src\YibinThesis' # yibinthesis_new 需要
defaultProjectDir: 'D:\thesis\my-thesis' # 留空则面板初始为空(推荐)
toolchainDirs: ['D:\src\YibinThesis\.tools']
| 键 | 默认 | 说明 |
|---|---|---|
templateRoot |
随包 vendor/yibinthesis |
模板运行时根(须含 build.ps1) |
cliRoot |
null |
上游检出根,提供 lib/yibinthesis_cli(yibinthesis_new 需要) |
pythonPath |
null |
跑适配器的解释器;留空用 PATH 上的 python |
toolchainDirs |
[] |
额外工具链搜索目录 |
toolchain |
{} |
按工具名直接指定可执行文件(优先级最高) |
defaultProjectDir |
null |
未传 project_dir 时的默认项目目录 |
buildTimeoutMs |
900000 |
单次构建墙钟预算(首次 Tectonic 要下载宏包) |
maxLogBytes |
262144 |
子进程输出采集上限,超限截断并置 truncated:true |
quiet |
false |
静音 info 级启动日志(warn 永不静音) |
非法配置在加载期响亮失败,不会静默回落默认值。
测试
node --test --test-timeout=120000 "tests/**/*.test.mjs"
84 个用例,按关注点分文件(tests/):
| 文件 | 用例 | 守住什么 |
|---|---|---|
contract.test.mjs |
17 | package.json / patch / vendor / 注册面自洽;技能 frontmatter 在 CRLF·BOM 下不退化 |
client-render.test.mjs |
21 | 真渲染(非快照):逐项内容断言、组件抛错必须可见、缓存跨卸载、目录优先级、写面恰好一个 |
bridge.test.mjs |
16 | 路由全集、写白名单、非法输入不得落盘、写回保真(其余字段原样) |
toolchain.test.mjs |
10 | 工具链发现优先级、PATH 去重、版本校验 |
local-toolbuilder.test.mjs |
8 | 自带 defineTool 与宿主真 DSL 的等价性 |
han-count.test.mjs |
6 | LaTeX 剥离口径:注释 / 公式 / 逐字环境 / 结构命令参数一律不计 |
real-dsh-tools.test.mjs |
4 | 用宿主真实 defineTool 验证 6 个工具定义合法 |
installed-entry.test.mjs |
2 | 已安装副本与源码逐字节一致 |
另有 scripts/check_han.py:汉字计数的硬断言式校对(自带期望值,非人工比对)。
目录
yibinthesis-dsh/
├── lib/ host 半:入口、工具、工具链探测、子进程、配置、HTTP 桥、客户端
├── adapter/ Python 适配器(结构化读取的唯一来源)
├── client 半 lib/client.js(__ModuleLoader__ 包裹格式)
├── skills/yibinthesis/ 技能 + references
├── vendor/yibinthesis/ 随包模板运行时
├── scripts/ 校对脚本(check_han.py)
├── docs/ 架构与安装
└── tests/ 84 个测试
发布(维护者)
# 1) 先跑测试与打包
npm test
npm pack # 产出 yibinthesis-dsh-<version>.tgz
# 2) 发布(用绝对路径指向 tarball,避免工作目录不对导致发错包)
npm publish "<仓库绝对路径>\yibinthesis-dsh-<version>.tgz"
必须使用 Automation token,不要使用交互式 2FA。 交互式流程走「暂存发布」:
若在浏览器确认环节中断,registry 会残留 0.0.0-stage 占位存根并占据
dist-tags.latest,其后发布会报 E409 Cannot publish over previously staged version。
Automation token 使 npm publish 成为非交互的单次操作:
# %USERPROFILE%\.npmrc
//registry.npmjs.org/:_authToken=<Automation token>
不要执行 npm unpublish:删除后 npm 会锁定该包名 24 小时不允许重发
(E403 cannot be republished until 24 hours have passed)。该限制作用于包名,
更换版本号无法绕过。
发布前确认工作目录为仓库根(npm pkg get name 应返回 yibinthesis-dsh)。
用户主目录下若存在用于存放依赖的 package.json,在其中执行 npm publish
会使 npm 将该目录当作包根并遍历,进而扫到受保护的系统目录
(AppData\Local\ElevatedDiagnostics)而报 EPERM scandir。
授权
MIT。随包 vendor/yibinthesis/ 来自上游 YibinThesis(MIT)。
校名、校徽等机构标识不在 MIT 授权范围内,详见 NOTICE。