dsh-novel-reader
IdentifiedReads local txt novels inside the chat dialog: chapters are detected automatically, the novel text is paginated in the assistant thinking block, a next-chapter button continues in the same reply, prog
小说阅读插件(dsh-novel-reader)
把本地 txt 小说变成 DSH 里的「对话」:在小说目录里放 txt,在输入框旁边选中一本,之后每发一条消息,助手就流式读出一章正文。它看起来和正常 AI 回复一样(正文藏在「思考」里),但内容全部来自你自己的小说文件,不联网、不调用模型。
适合摸鱼
使用示例
配置目录和小说别名
选择小说
阅读小说
安装
本插件是一个标准的 DSH bundle(package.json 里声明 dsh.bundle.patch 和 dsh.client,无需构建、无第三方运行时依赖)。
- 从 GitHub 安装:
git clone https://github.com/ukkyo1/dsh-novel-reader.git,然后在插件管理器(设置 → 插件 → 添加插件)里选本地目录安装;插件管理器如果支持 Git 地址,也可以直接填仓库地址。 - 本地目录安装:插件管理器选择从本地目录安装,目录填仓库根目录,安装并启用。
- 离线包:直接下载 Release 里的 tgz 作为本地包安装(取决于插件管理器版本是否支持 tgz);或在仓库根执行
pnpm pack自己打一个。 - 启用后刷新一次 Web GUI 页面(
Ctrl+R),输入框旁的「阅读模式」按钮就会出现;新会话也可以直接用。
升级时在插件管理器里禁用再启用本插件(或重启 DSH),并刷新页面以加载新的浏览器半代码。
快速开始
-
确认小说目录
默认目录是 DSH 主目录下的
novels:<DSH_HOME>\novels本机通常是
C:\Users\<你的用户名>\.dsh\novels(DSH_HOME由 DSH 实际安装位置决定,不写死用户名)。目录不存在时,插件第一次加载会自动创建;也可以在 设置 → 小说阅读 里直接改(支持手动输入或用「选择文件夹…」)。 -
把 txt 放进目录
直接复制粘贴
.txt文件进去即可。建议保存为 UTF-8 编码,避免中文乱码。目录里放多少本都行,子目录不会被扫描。 -
在会话里选中小说
打开任意会话,看输入框底部那一行工具栏:在模型选择器左边有一个小小的「阅读模式」按钮。点它,会弹出小说列表(和模型选择框长得差不多),每一行是书名和阅读进度(有章节的书显示「第 3/120 章」)。点一本,本会话就进入阅读模式;按钮上会显示「书名 · 第 3/120 章」。
-
发消息继续读
随便发一句话(「继续」「下一段」都行,内容本身不影响结果),助手就会开始"思考"并且流式输出下一章的正文。默认模式下:
- 小说正文放在**「思考」折叠块里:点一下「思考」展开后是左右点击翻页**的阅读器,不再是一大段需要滚动的文字。整章会自动按页面高度切页,点页面右侧翻到下一页、左侧上一页,新页从侧边覆盖旧页(没有滚动动画);页脚显示章节和「第 x/y 页」。同一段正文的翻页位置会记住,收起再展开仍停在原页。
- 读到本章最后一页时,下一页按钮会变成「下一章 ›」:点一下就在同一个阅读页里载入下一章(进度、章节标签随之更新),不需要再发消息、重新展开思考;读完最后一章显示「全书完」。
- 阅读页会按宿主思考区域的最大高度自动收缩页高,避免出现「每页都要滚动才能看全、按钮被顶到下面」的情况。字号、行距、字间距、段间距、页高、页边距、最大宽度、字体都可以在 设置 → 小说阅读 → 阅读样式 里调,改完立即生效(也可以在配置里设默认值)。
- 可见的助手回复是一段固定的结构化总结:默认是一份较长的报告(处理范围 / 处理结果 / 状态表 / 整体进度 / 说明 / 下一步),占据正常 AI 回答应有的页面高度,看起来就是一次带思考过程的完整答复。总结里的整体进度会随阅读推进变化。
- 翻页正文的字号、行距、字间距、段间距、页高、页边距、最大宽度、字体都可以在 设置 → 小说阅读 → 阅读样式 里调,改完立即生效(也可以在配置里设默认值)。
- 生成速度在 设置 → 小说阅读 → 生成速度 里三选一:瞬间生成 / 指定整段秒数 / 按字每秒。正文页面是固定页高、超出部分自动分页,不会出现滚动条,翻页按钮就在页面下方。
章节自动识别:插件会扫描 txt 里单独成行的章节标题——
第一章 …、第1章 …、第 12 节、第 3 回、Chapter 1,以及楔子/序章/引子/番外/尾声/后记等。读到标题就切一章,一条消息读一整章;第一个标题之前的内容(书名页、作者的话)并入第 1 章。没有识别到任何章节标题时,自动退回原来的「按字数切段」模式(chunkChars生效)。数字跳章:在阅读模式下,直接发一个数字(
1、2、3…)就会跳到对应序号的章节,并立刻把那一章读出来。序号是按标题出现顺序编的(楔子/序章算 1 号);发超出范围的数字会提示总章数,进度不变。输入框旁边的面板底部也有一行提示。不想用这个功能可以关掉numberedJump。回复走的是 DSH 正常的助手消息渲染管线:字体、行高、段落间距与真实模型回复完全一致。插件会把原文每一行整理成一个 Markdown 自然段(段间空行),并转义正文里的
*、反引号、#、-等符号,避免被渲染成标题/列表;同时按真实模型的节奏逐字出字(首字前有一小段停顿)。想让正文直接就是可见回复(不放进思考块),把配置里的
display改成answer即可。当前界面的「思考」折叠时机是「下次输入时」(DSH 全局设置
ui-chat.collapseTiming: next-input),所以回复刚结束时思考块是展开的,下一次发消息后才会收起。想让它一完成就折叠,可在cordis.patch.yml的ui-chat那行把collapseTiming改成completion——这是全局设置,会影响真实模型的思考显示。 -
退出阅读模式
再点一次那个按钮,在弹出面板最下面选「退出阅读模式」。退出后本会话恢复正常 AI 对话,之前的聊天记录不受影响。
如果目录还是空的,面板里会显示「固定目录里还没有 txt 文件」和一个「创建示例小说」按钮,点一下就会把插件自带的两篇示例写进目录,方便先试手感。
设置页
打开「设置」→「小说阅读」,可以集中管理所有小说:
- 小说目录:页面顶部是可编辑的目录输入框,支持手动填绝对路径或点「选择文件夹…」;「应用」后立即切换并重新扫描,「恢复默认」回到
<DSH_HOME>\novels。进度和显示名按目录分别保存(存在该目录下的.reader-state.json),换目录相当于换一个书库,旧目录的进度不会带过来。- 如果
cordis.patch.yml里显式写了directory,目录会被配置固定,设置页只显示不可编辑(会有一行提示)。 - 设置页选择的目录记在
<DSH_HOME>\novel-reader.settings.json,重启后仍然生效。
- 如果
- 显示名:每本小说都可以在输入框里改成任意名字(这个名字就是按钮和列表里显示的书名),点「保存」生效。改显示名不会改动磁盘上的文件名,也不会影响进度。
- 阅读样式:页面下半部分可以调翻页正文字号、行距、字间距、段间距、页高、页边距、最大宽度和字体(CSS
font-family),以及翻页效果(无动画 / 快速覆盖 140ms / 标准覆盖 280ms),保存后立即应用到所有阅读页面;「恢复默认样式」回到cordis.patch.yml里的默认值。 - 生成速度:三选一——瞬间生成(不逐字出)、指定整段秒数(按「正文 + 总结」的总片段数均摊)、按字/秒。点选/改数值后立即保存生效;「恢复默认速度」回到配置默认值(默认是瞬间生成)。
- 进度:有章节的书显示「第 3/120 章 · 已读 2% · 420 / 123456 字」,没有章节的书只显示百分比和字数。
- 重置进度:把这本书的进度归零,下次从第一段开始读。
- 创建示例小说:目录为空时会出现这个按钮,把插件自带的
samples/sample-story-1.txt、samples/sample-story-2.txt复制进固定目录(同名文件已存在则跳过)。
进度是怎么记住的
- 进度按小说保存,最小单位是「字符偏移」,也就是读到了全书第几个字符,而不是第几段或第几页。
- 章节模式下,正常读完一章后进度停在下一章开头;数字跳章会直接把进度设到目标章节开头(再倒退跳也可以)。
- 进度记录与具体会话无关:在 A 会话读到 40%,换到 B 会话选同一本书,也会从 40% 继续;反过来,两个会话同时读同一本书,进度是共享的、后读的会推进它。
- 这些数据保存在小说目录下的隐藏文件
.reader-state.json里(显示名、每本进度、会话与小说的对应关系都在里面)。删掉它等于重置全部进度和改名。 - 每读完一段就写一次磁盘;中途点「停止」时,已经显示出来的那部分也算读过了,下次会从断点接着往下读。
- 刷新页面、重启 DSH 都不会丢进度。整本书读完之后,列表里会显示「已读完」,再发消息会提示已经读完。
- 想重新读一遍,用设置页的「重置进度」。
配置(高级)
插件在 cordis.patch.yml(DSH 配置目录下的补丁层)里对应一行配置,可以调三个参数。改完后让插件重新加载(禁用/启用本插件,或重启 DSH)生效:
- id: novel-reader
name: dsh-novel-reader
config:
directory: "" # 小说目录;留空 = <DSH_HOME>/novels(设置页可改)
chunkChars: 420 # 无章节标题时的切段字数(80 - 4000)
streamMode: instant # instant=瞬间;duration=整段固定秒数;speed=固定字/秒
streamSeconds: 4 # duration 模式的秒数(0.5 - 60)
streamCharsPerSecond: 200 # speed 模式的速度(字/秒,10 - 5000)
firstTokenDelayMs: 350 # 首字之前的停顿,毫秒(0 - 3000);instant 模式忽略
display: thinking # thinking = 正文放思考里、可见固定总结;answer = 正文就是可见回复
summaryTemplate: "" # 可见总结模板;留空用内置长报告,支持 {title} {percent} {offset} {total}
chapters: true # 自动识别章节,每条消息读一整章
numberedJump: true # 纯数字消息跳转到对应序号的章节
maxChapterChars: 0 # 单条回复最多输出多少章节字数;0 = 不限
sessionTitle: "" # 会话标题;留空用内置普通工作型标题池(不出现书名)
readingFontSize: 15 # 翻页正文字号(px)
readingLineHeight: 1.8 # 行距(倍)
readingLetterSpacing: 0 # 字间距(px)
readingParagraphSpacing: 0.8 # 段间距(行)
readingPageHeight: 440 # 每页正文区高度(px)
readingPagePadding: 18 # 页面内边距(px)
readingPageMaxWidth: 0 # 页面最大宽度(px,0=自适应)
readingFontFamily: "" # CSS font-family,留空继承
readingFlip: fast # 翻页效果:none / fast(140ms) / normal(280ms)
| 配置项 | 默认值 | 说明 |
|---|---|---|
directory | <DSH_HOME>\novels(即 C:\Users\<用户名>\.dsh\novels) | 小说目录。留空(推荐)时用默认目录,并允许在设置页随时修改;填绝对路径(或相对 DSH_HOME 的路径)则目录被配置固定,设置页不能改。 |
chunkChars | 420 | 没有识别到章节标题时,每次回复「一段」的字数基准。取值范围 80 - 4000。 |
streamMode | instant | 出字方式:instant 瞬间生成;duration 整条回复(正文+总结)用固定秒数出完;speed 按固定字/秒出。 |
streamSeconds | 4 | duration 模式的秒数(0.5 - 60)。 |
streamCharsPerSecond | 200 | speed 模式的速度(字/秒,10 - 5000)。 |
firstTokenDelayMs | 350 | 开始出字之前的停顿,模拟真实模型的「思考时间」。instant 模式会忽略它。取值范围 0 - 3000。 |
display | thinking | thinking:小说正文进「思考」折叠块,可见助手回复是固定总结;answer:小说正文直接作为可见回复。 |
summaryTemplate | 空(内置较长的结构化报告) | 仅在 display: thinking 时生效。自定义可见总结的 Markdown 文案,支持 {title} {percent} {offset} {total} 占位符;留空用内置长报告。 |
chapters | true | 自动识别章节标题、每条消息读一整章。设为 false 则退回按 chunkChars 切段。 |
numberedJump | true | 阅读模式下,用户只发一个数字时跳到对应序号的章节并直接读它。 |
maxChapterChars | 0 | 单条回复最多输出多少章节字数,用于防超长章节一次读太久;0 = 不限。被截断时下一次回复继续同一章。 |
sessionTitle | 空 | 阅读模式会话的标题。留空时从内置的普通工作型标题池(「内容整理」「继续处理」「分段梳理」等)按会话 id 稳定选一个,不会出现书名。 |
readingFontSize | 15 | 翻页正文的字号(px,12-40)。 |
readingLineHeight | 1.8 | 翻页正文的行距倍数(1.2-3)。 |
readingLetterSpacing | 0 | 字间距(px,0-8)。 |
readingParagraphSpacing | 0.8 | 段间距(以行高为单位,0-3)。 |
readingPageHeight | 440 | 每页正文区高度(px,240-1200)。翻页按这个高度切分。 |
readingPagePadding | 18 | 页面内边距(px,0-64)。 |
readingPageMaxWidth | 0 | 页面最大宽度(px,0 = 跟随正文宽度)。 |
readingFontFamily | 空 | CSS font-family,例如 "Noto Serif SC", serif;留空继承界面字体。 |
readingFlip | fast | 翻页效果:none 无动画直接切换、fast 140ms 快速覆盖、normal 280ms 标准覆盖。 |
关于按字数切段:只有没有识别到章节标题的书才会用这个模式。插件先取
chunkChars个字,然后尽量对齐到原文的自然段换行处收尾(最多再多看六成篇幅),所以实际一段大约是 420 到 670 字;找不到合适的换行时会按字数硬切。
会话标题
阅读模式的会话标题不再用《书名》(那样太怪),而是从一组普通工作型标题里按会话 id 稳定选一个:「内容整理」「继续处理」「分段梳理」「续接推进」「长文处理」「整体梳理」。想固定成某个标题就配 sessionTitle。
注意:会话标题只在会话第一次生成回复时写一次。之前已经生成过《sample-story-1》这类标题的旧会话不会自动改,手动重命名一下那个会话,或者新开一个会话即可。
已知限制
- 一次只扫描一个目录:可以在设置页切换目录,但不支持同时挂多个目录、不扫描子目录。
- 只支持 .txt:epub、mobi、docx、pdf 概不支持,也不支持压缩包。txt 请用 UTF-8 编码保存。
- 目录可以换,但进度不迁移:设置页换目录后按目录重新开始(每个目录有自己的
.reader-state.json)。想保留旧目录的进度就换回去。 - 只在 Web GUI 里可用:按钮和设置页都是 Web GUI 的界面部分,没有对应的命令行入口。
- 章节识别是启发式的:只认「单独成行、长度不超过 80 字、不含句号」的标题行,比如
第一章 出发、第1章、第 12 节、Chapter 3、楔子、番外 …。标题和正文挤在同一行、或用了非常规写法时可能识别不到,此时会自动退回按字数切段;不会报错。 - 数字跳章的序号按标题出现顺序编:如果书里有楔子/序章,它们也算一个序号(例如楔子=1、第一章=2)。发数字前可以先看设置页/按钮上的「第 X/Y 章」。
- 阅读模式下没有真正的模型回答:只要会话处于阅读模式,用户发出的消息、会话标题、上下文压缩摘要全部由插件接管,回复内容只来自小说正文。此时不要期待模型真的回答了你的问题,也不要把它当检索工具——需要正常提问时,请退出阅读模式,或者另开一个会话。
- 翻页按页面高度自动切分:同一段正文会按你设置的页高/字号/行距切成若干页;如果某一段特别长(超过一整页),会优先在句号、问号、分号处断开,不会出现滚动条。
- 极长的单本 txt(几十 MB)首次扫描和计算字符数会稍慢,属正常现象。
故障排查
| 现象 | 原因与处理 |
|---|---|
| 小说目录不存在 | 不用手动创建,插件在第一次加载时会自动创建空目录。如果创建失败(权限问题),请手动新建该目录,或把 directory 指到一个可写目录。 |
| 列表里没有刚放进去的书 | 点设置页的「刷新列表」(或重新打开面板)重新扫描;确认扩展名是 .txt、文件放在目录根下而不是子目录里。 |
| 换了目录之后看不到旧进度 | 进度按目录保存,换目录等于换书库;换回原目录即可看到原来的进度。 |
| 设置页目录是灰的、提示被配置固定 | cordis.patch.yml 的 directory 写了路径;把那一项留空并重载插件后,就能在设置页改。 |
| 填了新目录点「应用」报错 | 目录不可创建或不可读;换一个可写目录,或检查路径拼写(支持绝对路径,相对路径按 DSH_HOME 解析)。 |
| 把文件改名之后 | 改名会被视为一本新小说,旧条目的进度不再跟随,新条目从 0% 开始。想找回原来的进度,把文件名改回去即可。 |
| 删除文件之后 | 对应的条目会从小说列表里消失;如果那个会话正在读这本书,会自动退出阅读模式,回到正常 AI。 |
| 一不小心读完了 / 想从头再读 | 设置页点「重置进度」,或在面板里换另一本书。 |
| 列表里出现没见过的隐藏文件 | 插件只显示 .txt,并跳过 .reader-state.json 这类以点开头的文件,所以正常不会看到。 |
| 中文显示成乱码 | 用记事本或 VS Code 把 txt 另存为 UTF-8(无 BOM 也可以)。 |
| 按钮点了没反应 / 显示「读取失败」 | 插件宿主尚未就绪或目录不可读,稍等几秒再点;仍失败就重启 DSH 并查看主进程日志。 |
| 回复太慢或太快 | 到设置页「生成速度」切换:瞬间生成 / 指定秒数 / 字每秒;也可以在配置里改 streamMode / streamSeconds / streamCharsPerSecond。每段太长或太短就调 chunkChars(仅在无章节时生效)。 |
| 章节没识别出来 / 一直是按字数在切 | 确认章节标题单独占一行(如 第一章 出发),不要和正文写在同一行;识别到后设置页/按钮会显示「第 X/Y 章」。 |
| 发数字没反应或提示总章数 | 只有识别到章节的书才支持数字跳章;序号范围是 1 到总章数;想关闭就设 numberedJump: false。 |
| 想退出阅读模式却找不到 | 点输入框旁的按钮,在弹出面板底部选「退出阅读模式」;英文界面里是最下面那一项。 |
开发与测试
npm run check:对宿主/浏览器两半做语法检查。npm test:宿主半自动化测试(用假 ctx 装载index.js,覆盖目录扫描/切换、阅读样式、生成速度、章节检测、整章阅读、数字跳章、切段、流式、中断续读、标题、压缩、改名、重置、持久化、RPC envelope)。node test/chapter-check.mjs <某本小说.txt 的绝对路径>:拿真实 txt 验证章节检测、整章阅读、数字跳章;脚本会复制到临时目录,不改动原文件。
附带文件
samples/sample-story-1.txt:《老邮局的值夜人》,悬疑短篇,14 段(无章节标题,按字数模式)。samples/sample-story-2.txt:《潮汐图书馆》,奇幻短篇,15 段(无章节标题,按字数模式)。samples/sample-story-3-chapters.txt:《渡口旧事》,4 章(有章节标题,可直接试「整章阅读」和「发 1/2/3/4 跳章」)。
两篇均为原创示例文本,用来验证「一段一段读」的体验(它们没有章节标题,所以走按字数模式),可直接当小说读,也可以删掉换成自己的书。
Versions
| Latest version | Published | Size |
|---|---|---|
| 0.9.4 | — | — |
Comments
Loading…
Similar plugins
Local TXT reader in a right-sidebar tab plus a spoiler-safe AI reading companion: the model only sees what you have already read — the current chapter, the tail of the previous chapter, and a per-book
★ 2
MIT
JavaScript
dsh plugin --profile web add dsh-reading-companionLocal TXT novel reader in the DSH right sidebar: bookshelf with file, directory and path import, chapter table of contents with jump, click-to-turn or vertical-scroll paging, reading progress restored
★ 0
dsh plugin --profile web add dsh-novel-readerIn-browser novel reader for the dsh web GUI: online book-source search, chapter-by-chapter reading in a chat-style view, and whole-book TXT download.
★ 0
dsh plugin --profile web add github:Wodexinhaoleng-Kasssa/dsh-readerby xrn1997
Read web novels inside the DSH web GUI: import legado book sources, aggregate search across sources, a bookshelf with reading progress, continuous-scroll reading, and five agent tools for search, chap
★ 3
Apache-2.0
TypeScript
Nov 6, 2026
dsh plugin --profile web add @xrn1997/dsh-novelby gongfpp
Read local EPUB, TXT and Markdown novels below selected native DSH chat regions on explicit expansion, preserving real reasoning and tool output without sending novel text to the model. Currently work
★ 2
MIT
JavaScript
Nov 9, 2026
dsh plugin --profile web add @gongfpp/dsh-novel-fishby qinpeizhan77
Local-first fiction workspace that links outlines, chapters, characters, timelines, writing rules, and continuity checks to the conversation.
★ 10
↓ 258/wk
MIT
TypeScript
Aug 30, 2026
dsh plugin --profile web add deepseek-harness-novel-studio