Releases: wbb316/dsh-novel
Release list
v0.13.0 · 开书向导 + 设定.json
v0.13.0
这一版是开书体验版本:把「新建小说」从一个两栏小表单,改成整页的开书向导,
并新增一个机器可读的 设定.json。
为什么值得升:开一本新书时你脑子里那些「主角是谁、这本书什么调子、打算往哪走」,
以前只能硬塞进「一句话简介」里;现在有地方填,而且填完会落成文件 ——
下次写下一章时我读得到,不至于把甜文写成厚重悬疑。
📝 开书向导(单独一页)
点「+ 新建」,不再是列表下面弹出的小框,而是整页切换成向导:
- 五个折叠区:基本 / 主角 / 世界观 / 大纲 / 进阶,一页滚动到底
- 任何字段都能留空 —— 先开书、再慢慢补;缺的到「角色 / 设定 / 剧情」页里继续填
- 4 套模板:校园恋爱 / 都市异能 / 悬疑 / 空白。点一下只补空着的字段,
绝不覆盖你已经写的(写小说的人中途改主意是常态,覆盖式模板一定会被骂) - 「✨ 让 AI 帮我补全」:把这张表丢进对话输入框(走的是「写下一章」同一条路),
缺的我替你定 —— 主角补成一个有欲望也有弱点的人,世界观补三条规则一条禁忌,
三幕各补两三句,再往剧情表里放 5~8 个情节点 - 点「创建这本书」一次性落盘:
设定.json+角色.json(主角进"重要"档)+人物卡.txt+世界观.txt+大纲.txt剧情.json的卷纲领(可选顺手建一个空的第一章)
主角那几栏(身份 / 外貌 / 想要什么 / 怕什么 / 秘密 / 说话风格)会拼进角色的 desc,
性格关键词与身份进 tags(面板里显示成小标签)—— 不动角色表的 schema,老项目也读得懂。
⚙️ 新增 设定.json(机器可读的元信息)
| 字段 | 干什么用 |
|---|---|
| 类型 / 基调 / 视角 | 「这本书是什么」——续写时的准星 |
| 每章目标字数 | 决定一章写多长(以前只能靠猜) |
| 主线 / 结局 | 写长篇最容易迷路的两个地方 |
| 标签 / 备注 | 自由记;备注适合放"写作纪律" |
- 面板「设定」页里用表单改(跟向导同一套字段),想手改原文点「直接改 JSON」,
两边切换时会互相带上当前值(不然切过去看到一片空白,你会以为改动丢了) - 写下一章时,
novel_context会先给一段「这本书是什么」,再给大纲 / 世界观 / 角色 / 最近章节 - 为什么不塞进
大纲.txt:那是你随手写散文的地方。机器要读的东西放 json,两边互不打扰 - 字段有白名单:多写的键、写错的类型,保存时会被安静地洗掉(不是报错);
写坏了 JSON 会明确拦住并告诉你哪里不对
🕰️ 老项目不受影响(这条特意做了防呆)
设定.json 没有"老英文名"。如果把它塞进「新名 ↔ 老名」那张对照表,会让每一本新书
都被判成老格式 —— 大纲转头去读根本不存在的 outline.md。所以它是独立的固定文件名,
并且专门写了一条断言盯着这件事:有 设定.json 的书,大纲仍解析到 大纲.txt;
反过来,给你那些老项目(outline.md 那套)存一份 设定.json,也不会把格式带跑。
📦 安装 / 升级
dsh plugin --profile web add github:wbb316/dsh-novel需要 DSH 0.2.0-rc.1 或更高。装完重启一次 —— 客户端的 bundle 是宿主启动时组合的,
只刷新浏览器看不到新面板。
🧪 测试
17 个测试文件 / 1367 项断言全绿。本次新增:
- 开书向导的完整链路:模板只补空位、任何字段可留空、返回后再开一次草稿不残留、
创建后逐个核对落盘的文件(设定 / 角色 desc 拼装 / 世界观禁忌 / 剧情纲领 / 第一章空稿) 设定.json的读写与洗数据(新增test-setup.mjs):没有文件也算正常、坏 JSON 被拦住、
白名单丢掉野键、非法字数归零、标签 trim 与拆分- 两条防线:「续写上下文里必须带设定」和「老项目不许被
设定.json带偏」 - 顺手修掉一个只有测试能抓到的 bug:向导里同一个 tick 连改两个字段时,闭包里的旧 state
会把前一次吃掉(测试里连着设「书名 + 简介」,书名就没了;真人粘贴、连点模板同样会中招)。
现在一律用函数式更新,并留了断言守着
v0.12.0 · 面板迁到宿主原生席位(不再依赖 dsh-better-sidebar)
v0.12.0
这一版是兼容性版本:把面板从第三方侧栏搬到宿主自带的席位上,并主动声明版本要求。
挑这个版本号是因为面板出现的位置变了(右侧栏 → 左侧栏),你会直接看见。
🔧 改了什么
面板搬到宿主原生席位,不再依赖 dsh-better-sidebar
- 以前:借
dsh-better-sidebar的registerTab()往右侧栏塞一个页签。
代价是那个插件一卸面板就没了;它的版本范围一变,连宿主升级都会被它拦住。 - 现在:用宿主自带的席位系统 —— 左侧栏一行(
sidebar.panellist)+ 主区页面(main)。
面板的入口从右侧栏挪到了左侧栏(那一列图标里的书本图标),点开在主区里用。 - 老宿主照样能用:没有
ctx.slots的版本会自动退回原来的右侧栏页签。
这个回退是"机会主义"的(dsh-better-sidebar装不装都不影响本插件加载)。
声明版本要求:让宿主替你拦住不兼容
package.json 现在声明了 5 条 @deepseek-ai/dsh-* 的 peerDependencies 和 dsh.engines.dsh。
dsh 0.2.0 起,宿主启动时会检查每个插件的这些范围:不满足就直接拒绝加载并说明原因,
而不是像以前那样"跑起来看着没事、某天突然坏掉"。
📦 安装 / 升级
dsh plugin --profile web add github:wbb316/dsh-novel需要 DSH 0.2.0-rc.1 或更高。装完重启一次 dsh web(宿主要重新组合插件树);
以后只改客户端半的话刷新浏览器即可。
🧪 测试
16 个测试文件 / 1281 项断言全绿。本次新增两类断言:
- 8 条盯原生席位注册:席位没被声明之前不许注册、左侧栏条目的
id与主区页面的key
必须对齐、图标必须带data-dsh-panel-entry锚点、有原生席位时不许再重复挂旧页签、
主区页面要能真渲染出面板。以前只测了"回退路",等于没测主路 —— 这次补上了。 - 18 条盯清单不变式(新增
test-manifest.mjs):dsh.client.inject只能写有客户端半的包 id、
客户端半的exports.inject只能写服务名、两组不许写混、peerDependencies与
dsh.engines.dsh必须齐全。写这一版时我把两处 inject 都写成了包 id(其中
@deepseek-ai/dsh-client-ui-slots还是纯库,没有客户端半)——那会让宿主永远等不到这个模块,
面板凭空消失而且控制台不报错。这个文件就是那次事故的护栏(把 bug 造回去,它会红 3 条)。
v0.11.2 · 剧情任务栏 + 角色分档 + 改名全文替换(附三个修复)
v0.11.2
这一版把 9 月 29 日这一天的改动一起发了:新增「📋 剧情」页和角色分档,改角色名会全文替换,
另外修了三个用起来会卡住的地方。
✨ 新功能
📋 剧情(任务栏)
把大纲拆成一条条情节点,按卷分组显示:
- 一个情节点可以挂 0~N 章(一个剧情写好几章);一章也能挂好几个情节点
- 点 ☐ / ☑ 手动标记写完;另外插件会按「挂的章节都有正文」算出自动已写
(手勾优先;把正文删了,自动那勾会自己掉) - 每卷可以写一段纲领(这一卷这十几章往哪走)
- 情节点里能勾「出场角色」——遇到剧情里提到、但角色表里没有的名字,就地「+ 记成路人」
- 点「✍️ 写下一章」时,请求会自动带上还没写的情节点 + 本卷纲领
数据存在 <小说>\剧情.json,同时生成一份人可读的 剧情.txt;大纲.txt 不受影响,还是随手写散文的地方。
👥 角色分「重要 / 不重要」两档
- 角色页顶上是两个入口:「重要的角色(N)」「不重要的角色(N)」,点哪个看哪个,
关系也只显示跟这一档有关的 - 剧情里出现过的每个人都该在角色表里:带名字的路人也记,放「不重要」并标明身份(比如「路人」);
不写分档时会按身份猜(路人 / 龙套 / 群众 → 不重要) - 人物卡
.txt也按两档分节(只有一档时不加小标题,输出跟以前一样)
✏️ 改角色名 = 全文替换(会动正文,所以先算再问)
- 在名字框改了名字不会直接生效:先弹出确认,把「会改哪几个文件、各几处」列出来
- 点确定才动,而且先把原件整份备份到
<小说>\_改名备份\<时间>\再替换 - 范围:大纲 / 世界观 / 所有章节正文 / 剧情表的标题与备注
人物卡.txt、剧情.txt是生成的,不直接改(会跟着重新生成)- 只有一个字的名字不做全文替换(「晓」出现在「晓得」里太正常了),只改角色表并在确认框里说明
- 刚「+ 新角色」还没保存的角色直接改就行(正文里不可能有它)
🐛 修复
- 只有一本小说时,书名那一行点不动 —— 小说库(改名 / 删除 / 搜索)的入口被藏起来了。
现在永远可点。 - 角色少于 2 人时,关系区摆着两个只能选自己的下拉框,点了还报错。
现在直接说明差什么("至少要有 2 个角色"),「到」里也不再列出「从」选的那个人。 - 情节点挂在"还没建的卷"上时会整个消失(分组只遍历了磁盘上已有的卷)。
现在分组会把情节点里提到过的卷也算上。
🧪 测试
15 个测试文件、1255 项断言全绿(不启动 DSH、不占端口)。
哪个文件管哪块、怎么在本地跑,见 README 的
开发和自测。
📦 安装 / 升级
dsh plugin --profile web add github:wbb316/dsh-novel
dsh webv0.11.1 · 修复:导出的 docx 在 Word 中打不开
v0.11.1
修复 v0.11.0 导出的 .docx 无法在 Microsoft Word 中打开的问题;
同时清理导出的电子书里残留的 markdown 记号。
如果你在用
v0.11.0:它导出的 docx 是坏的,请更新到这一版。EPUB 不受影响。
🐛 修复
1. .docx 在 Word 里打不开
现象:双击 docx,Word 提示
Word 在试图打开文件时遇到错误。
原因:<w:t> / <w:br> 被直接写在 <w:p> 下面,缺少必需的 <w:r>(run)包裹。
这是非法 OOXML —— 但文件本身是合法 ZIP、XML 也是 well-formed,
所以「解压 + XML 解析」这类检查发现不了,只有 Word 会拒绝打开。
也说明「自动测试全绿」不等于「外部工具能打开」。这一版给仓库补了对应的回归断言。
2. 电子书里残留 markdown 记号
章节和设定读的是原文,导致 Word / 阅读器里会出现 ## 一句话简介、**苏晚**;
老格式项目的章节首行是 # 第1章 xxx,因为带 # 而没被剥掉 → 标题重复两遍。
现在统一走 plainForEbook():先抹掉 markdown 记号,再去掉首行的「第N章 标题」
(电子书的标题由结构提供:卷 = 标题 1、章 = 标题 2,正文里不该再出现一次)。
✅ 验证方式
不是「看着像对」,是拿外部工具实测过的:
| 验什么 | 用什么 | 结果 |
|---|---|---|
| EPUB 合规 | epubcheck 5.1.0(W3C 官方) | No errors or warnings detected(0 fatal / 0 error / 0 warning) |
| DOCX 能开 | Microsoft Word(COM 自动化,隐藏窗口、只读打开) | 正常打开,卷 = 标题 1、章 = 标题 2、大纲级别正确 |
| 正文干净 | 在 Word 里检索 | 没有 ##、没有 **,章标题只出现一次 |
测试用书:一部两章的中文小说(平铺与分卷两种结构都跑过)。
🔍 你可以自己验
# EPUB:W3C 官方的 epubcheck(需要 Java 11+,解开压缩包即可用)
java -jar epubcheck.jar "D:\dsh-novel\我的小说\我的小说.epub"
# 期望输出: No errors or warnings detected.DOCX 最省事:双击,用 Word / WPS 打开 —— 能翻页、标题有层级、正文里没有 # **,就是对的。
README 里还有一节「🔍 怎么自己验证 EPUB / Word」,含一段隐藏窗口打开 Word 检查页数与样式的脚本。
🧪 测试
13 个测试文件、1088 项断言。本次新增:
test-ebook.mjs:每个w:t/w:br都必须包在w:r里(撤掉修复验证过这条断言确实会失败)test-volume.mjs:plainForEbook()的抹记号 / 去标题 / 无标题正文原样保留
📦 安装 / 升级
dsh plugin --profile web add github:wbb316/dsh-novel
dsh webv0.11.0 · 卷/章 + 关系图自动布局 + 图片头像 + EPUB/Word 导出
dsh-novel v0.11.0 · 卷 / 章、关系图自动布局、图片头像、EPUB · Word
⚠️ 已知问题:这一版导出的.docx打不开请使用 v0.11.1 或更高版本。
导出的 docx 在 Microsoft Word 中会提示"Word 在试图打开文件时遇到错误"
(<w:t>缺少<w:r>包裹,属于非法 OOXML)。EPUB 不受影响。
详情与修复见 v0.11.1 的更新说明。
上一版「还没做」里的前四项,这一版全做完了(只剩多设备同步)。
老项目(平铺章节的小说)一个字都不用改:拿到的章节名还是原来那串,
想分卷再点「+ 新建卷」。
📚 卷 / 章
卷 = chapters\ 下的一个子目录:
chapters\第001章-开场.txt ← 未分卷(平铺)
chapters\第一卷 恋爱练习\第002章-x.txt ← 第一卷里的第 2 章
- 章节号全局连续 —— 第002章 进了第一卷也还是第002章,所以挪卷、删章都不会撞名
- 面板里章节按卷分组显示,卷标题自带 +(往这卷加章)/ 🖊(改名)/ 🗑️(删卷)
- 把章节拖到别的卷标题上 = 挪进那一卷(松手自动重新编号)
- 卷名排序认中文数字:第一卷 < 第二卷 < 第十卷 < 第十一卷(不会出现"第10卷排在第二卷前面")
- 删卷 = 整卷进回收站(跟删章节一个规矩,能捞回来)
- 导出 / 迁移 / 老格式一键转换都跟着认卷
🕸️ 关系图自动布局(力导向)
不再"摆一个圈":关系多的角色居中、关系近的挨着(Fruchterman-Reingold 简化版,纯手写零依赖)。
- 用固定种子,同样的角色/关系每次摆出来一模一样(不会刷一次界面跳一下)
- 收尾会按最小间距把圆点推开,名字不会叠在一起
- 手动拖过的位置照旧优先;点「🕸 自动布局」清掉手动位置、回到自动结果
🖼️ 图片头像
- 头像可以是 emoji / 姓氏(纯文本,永远可用),也可以上传图片
- 图片存成文件
<小说>\头像\<角色id>.png,角色.json里只记路径
(角色.json是留着给你用记事本改的,塞 base64 就毁了) - 关系图的圆点直接画图片头像;没有图片就自动退回 emoji
- 只认 png / jpg / webp / gif,≤ 2MB
📕 导出 EPUB / Word
点「⬇ 导出」选格式:
| 格式 | 内容 |
|---|---|
设定集.txt |
大纲 + 世界观 + 人物卡 + 章节清单(纯文本) |
| EPUB | 能直接丢进阅读器:设定当卷首、卷 = 分组、一章一节 |
| Word | 卷 = 标题 1、章 = 标题 2、中文友好字体 |
EPUB/DOCX 是自己写的 ZIP 打包器(只用 Node 内置的 zlib,零依赖)。
🧪 测试
13 个测试文件、1083 项断言,全部不启动 DSH、不占端口:
| 测试 | 断言 | 管什么 |
|---|---|---|
test-api.mjs |
63 | 假 req/res 打真路由(只读 + 400 错误路径) |
test-avatar.mjs |
55 | 新:图片头像(上传 / 出图 / 换格式 / 删除 / 坏输入 / 脏数据) |
test-bom.mjs |
31 | BOM 守卫(复刻 dsh web 启动那一步) |
test-cast.mjs |
52 | 角色 / 关系纯函数 |
test-client.mjs |
295 | 迷你 React 挂载面板,fetch 桩打到真路由 |
test-config.mjs |
47 | 保存位置 |
test-cordis.mjs |
16 | 真 cordis 生命周期(路由注入钩子) |
test-ebook.mjs |
90 | 新:EPUB / DOCX(自写 readZip 逐字节往返比对) |
test-library.mjs |
80 | 小说库记忆(纯逻辑) |
test-save.mjs |
195 | 写盘全链路 |
test-schema.mjs |
1 | 工具 JSON Schema |
test-stream.mjs |
66 | 流式缓冲(半截 JSON 抠字符串) |
test-volume.mjs |
92 | 新:卷 / 章(含跨卷挪动、卷名排序、回收站) |
EPUB 还做了独立交叉验证:用 Windows 自己的 Expand-Archive 解开,条目齐全、
mimetype 原文正确、中文不乱码、& < 转义正确 —— 不是"自己写自己验"。
📦 安装 / 升级
dsh plugin --profile web add github:wbb316/dsh-novel
dsh web⚠️ 已知限制(v0.11.0 发布后补记)
- 本版导出的 docx 无法在 Word 中打开 —— 见顶部告示,v0.11.1 已修复
- EPUB 已用 epubcheck 5.1.0(W3C 官方)验证:无错误、无警告
- 不支持 ZIP64(> 4GB 或 > 65535 个条目);EPUB 无封面图;DOCX 无页码与目录
- 多设备同步未实现(小说库记忆保存在浏览器本地,换设备是另一套)
补充说明:发布时的验证方式是「ZIP 可解压 + XML 可解析 + 90 项自动断言全绿」,
但这类检查发现不了 OOXML 的内容模型问题 —— Word 拒绝打开就是被这种检查漏掉的。
现在 EPUB 用 epubcheck、DOCX 用 Word 实测,且把这两条都写成了回归测试。
v0.10.1 · 修 BOM(带 BOM 的 package.json 会让 dsh web 起不来)+ 章节新建/正文编辑、老格式迁移、导出设定集、角色头像
dsh-novel v0.10.1 · 小说创作台 🖋️
DSH 插件:管你的小说项目(大纲 / 世界观 / 角色 & 关系 / 章节)——
一半给 agent 用(5 个 novel_* 工具),一半给人用(右侧栏「小说」面板)。
点一下就让 AI 带着大纲和角色关系接着写,边写边看它流出来的字。
这是第一个 Release,所以把
0.10.0那轮新功能和0.10.1的 BOM 修复一起发了。
🐛 修复:文件开头有 UTF-8 BOM,会让整个 dsh web 起不来
症状:dsh web 启动后 3080 根本没监听(浏览器就是打不开),日志里是
SyntaxError: Unexpected token '', "{"name"... is not valid JSON
根因:dsh-app-boot 在 loadProfileDirectory 里对每个 bundle 做
JSON.parse(readFileSync(pkg, "utf8")),而 JSON.parse 不认 BOM。
0.10.0 的 package.json 开头恰好带了 EF BB BF(Windows 侧工具写的:记事本
「另存为 UTF-8」、PowerShell 5.1 的 Set-Content -Encoding UTF8 / Out-File 都会加),
于是 composeProfile 阶段就抛错退出 —— 报错完全指不到「是某个插件的 package.json 有问题」,
能查很久。
⚠️ 装了0.10.0的,dsh web会起不来,更新到这一版即可。
这一版两头都堵上了:
- 清掉仓库里所有文件的 BOM(
package.json/README.md/lib/index.js/ 两个测试文件) - 新增
lib/text.js:从磁盘读进来的文本一律先去 BOM ——~/.dsh-novel/config.json、
角色.json、大纲 / 世界观 / 章节正文、请求体全走它
(也就是说:你用记事本改角色.json,也不会再把插件打瘸) - 新增
test-bom.mjs:仓库体检 + 照原样复刻dsh web启动那一步 + 走真路由读带 BOM 的用户文件 - 新增
.editorconfig(charset = utf-8,VS Code 保存即无 BOM) - README 踩坑清单从 17 条加到 18 条,把这个坑写进去了
✨ 新功能(0.10.0)
| 能干什么 | |
|---|---|
| ✍️ 章节自己写 | 「+ 新章节」建个空章节,直接在面板里写正文(Ctrl+S 保存,.txt 按纯文本存);改名 / 删除 / 按住拖动排序(松手自动重新编号) |
| 👥 角色头像 | 头像 1~4 个字符(emoji 或姓氏),会画在关系图的圆点上 |
| 🕸️ 关系图 | 节点可以拖,位置记在本地;关系用「从谁 → 什么关系 → 到谁」 |
| ⇪ 老格式一键迁移 | 老项目(outline.md 那套)在设定页会提示,点一下转成新格式,原件搬进 _旧格式备份\,不删 |
| ⬇ 导出设定集 | 把大纲 + 世界观 + 人物卡 + 章节清单合成一个 设定集.txt 放进小说目录 |
早几个版本里已经有的:📚 小说库(换书 / 记住每本读到哪 / 就地改名删除,删除 = 移到回收站)、
🎬 一键续写 + 流式直播(章节正文是当工具参数流出来的,从半截 JSON 里抠 content)、
📂 保存位置可配置(目录不存在自动创建)、自动刷新档位(实时 / 普通 / 省电 / 关闭 / 自定义)。
🧪 测试
10 个测试文件、796 项断言,全绿。全部不启动 DSH、不占端口:
| 测试 | 断言 | 管什么 |
|---|---|---|
test-api.mjs |
63 | 假 req/res 打真路由(只读 + 400 错误路径) |
test-bom.mjs |
31 | BOM 守卫 |
test-cast.mjs |
52 | 角色 / 关系纯函数、脏数据、指错人、渲染纯文本人物卡 |
test-client.mjs |
245 | 迷你 React 挂载面板(含子组件),fetch 桩打到真路由 |
test-config.mjs |
47 | 保存位置:自动建目录、夹取、环境变量优先、坏配置兜底 |
test-cordis.mjs |
16 | 真 cordis:先给 tools、后给 webServer,验证注入钩子会自己触发 |
test-library.mjs |
80 | 小说库记忆(纯逻辑):记住 / 回落 / 按库分组 / 坏数据 |
test-save.mjs |
195 | 写盘全链路(新建 / 角色 / 存稿 / 改名 / 删除) |
test-schema.mjs |
1 | 工具的 JSON Schema 是否合法 |
test-stream.mjs |
66 | 流式缓冲:帧折叠、半截 JSON 抠字符串、preview 降级 |
说明:
test-save/test-api跑在你真实的小说库里(只建__自测*临时作品,
跑完连挪进回收站的痕都清干净);其余跑在系统临时目录。
📦 安装 / 更新
dsh plugin --profile web add github:wbb316/dsh-novel
dsh web前置条件
| 说明 | |
|---|---|
| DSH | 0.1.5 或更高(用到了 agent/assistant-stream 流式帧) |
| Node | >= 20 |
| dsh-better-sidebar | 侧栏面板的容器;不装的话 5 个工具照常可用,只是没有面板 |
⚠️ 还没做
- 章节的多级结构(卷 / 章)—— 现在只有平铺的章节
- 关系图的自动布局(按关系亲疏摆位,而不是圆圈)
- 角色头像用图片(现在只能是 emoji / 字符,因为要保证项目里只有纯文本 + json)
- 导出成 epub / docx(现在只导出
设定集.txt) - 多设备同步(小说库记忆存在浏览器本地,手机上打开是另一套)