dsh-novel-writer 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -44
- package/client.js +72 -0
- package/cordis.patch.yml +1 -7
- package/lib/index.js +527 -420
- package/lib/pattern.js +125 -0
- package/package.json +13 -39
- package/INSTALL.md +0 -123
- package/lib/analysis.js +0 -549
- package/lib/client.js +0 -482
- package/skills/novel-writing/SKILL.md +0 -46
package/README.md
CHANGED
|
@@ -1,31 +1,25 @@
|
|
|
1
|
-
# dsh-novel-writer —
|
|
1
|
+
# dsh-novel-writer — 小说写作助手插件
|
|
2
2
|
|
|
3
|
-
DSH(DeepSeek Harness)小说写作助手 bundle
|
|
4
|
-
|
|
5
|
-
v0.3.0 新增**句式模式分析**扩展与 **Web UI 开关**。
|
|
3
|
+
DSH(DeepSeek Harness)小说写作助手 bundle 插件。零第三方依赖(仅 Node 内置模块),
|
|
4
|
+
为 AI 提供小说章节库管理、分析与续写辅助能力。
|
|
6
5
|
|
|
7
|
-
##
|
|
6
|
+
## 功能(对应需求)
|
|
8
7
|
|
|
9
8
|
1. **章节库**:章节存于 `novels/<书名>/第N章.md`(或 `.txt`/`.markdown`),
|
|
10
9
|
插件提供 `novel_books` / `novel_chapters` / `novel_read` 让 AI 浏览并读取每一章内容。
|
|
11
10
|
章节文件名中的序号支持任意位置与多种写法,例如:
|
|
12
11
|
`第01章.md`、`01-标题.md`、`原稿件-单章-…第一章.txt`、`原稿件-单章-第25章 .txt`
|
|
13
12
|
(阿拉伯数字与中文数字"第一章/第十四章/第三十章"均可识别,自动按章号排序)。
|
|
14
|
-
文件编码自动探测:UTF-8(含/不含 BOM)、UTF-16 LE/BE(含 BOM 或启发式识别)、GBK/GB18030(无 BOM
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
- 句长节奏:均值/中位数、短句/长句占比;
|
|
20
|
-
- 主观情感:轻量情感词典(喜/怒/哀/惧/惊)+ 强度副词加权 → 主导情绪、情绪分布、情感曲线、主观性指数;
|
|
21
|
-
- 风格指纹:一维紧凑签名,方便 AI 快速比对与复刻作者的句式习惯。
|
|
22
|
-
4. **UI 开关(v0.3.0 新增)**:Web GUI 侧边栏出现「句式分析」入口,面板内两个开关:
|
|
23
|
-
- **启用句式分析(enabled)**:控制 novel_sentence_analysis 是否可用;
|
|
24
|
-
- **自动分析(autoAnalyze)**:控制 AI 分析作品时是否主动附带句式报告。
|
|
25
|
-
开关实时写入宿主端 `~/.dsh/dsh-novel-writer/state.json`,与 `novel_sentence_config` 工具双向同步;
|
|
26
|
-
宿主端不可达时降级保存在浏览器 localStorage。
|
|
27
|
-
5. **续写**:系统提示词规定续写工作流(先读后写、保持文风与伏笔一致),
|
|
13
|
+
文件编码自动探测:UTF-8(含/不含 BOM)、UTF-16 LE/BE(含 BOM 或启发式识别)、GBK/GB18030(无 BOM),
|
|
14
|
+
无需手动转码即可读取(如记事本另存的 Unicode 文本)。
|
|
15
|
+
2. **分析**:`novel_keywords` 确定性提取全书/单章高频关键词(中文相邻二字词组 + 高频单字 + 英文词),
|
|
16
|
+
配合系统提示词引导 AI 分析剧情脉络、写作手法、词汇偏好与意象母题。
|
|
17
|
+
3. **续写**:系统提示词规定续写工作流(先读后写、保持文风与伏笔一致),
|
|
28
18
|
`novel_new_chapter` 创建新章节文件。
|
|
19
|
+
4. **原稿件批量导入/自动分类**:`novel_import` 扫描存放多本小说稿件的文件夹
|
|
20
|
+
(支持子文件夹、UTF-16/GBK 等编码、任意位置章号),从文件名与文件头内容双通道
|
|
21
|
+
提取书名候选并聚合成分组建议(scan 模式),AI 确认后可一键按书分类复制/移动到
|
|
22
|
+
`novels/<书名>/`(apply 模式);支持 `book` 强制归并异名同书、`files` 精确指定文件。
|
|
29
23
|
|
|
30
24
|
## 提供的工具
|
|
31
25
|
|
|
@@ -36,44 +30,49 @@ v0.3.0 新增**句式模式分析**扩展与 **Web UI 开关**。
|
|
|
36
30
|
| `novel_read` | 阅读某章正文(行号 + 字数统计,offset/limit 分段) |
|
|
37
31
|
| `novel_keywords` | 提取高频关键词(可单章或全书) |
|
|
38
32
|
| `novel_new_chapter` | 创建新章节文件(自动取下一个章号) |
|
|
39
|
-
| `
|
|
40
|
-
| `
|
|
33
|
+
| `novel_import` | 扫描原稿件文件夹,自动识别/分类多本小说章节到 `novels/<书名>/`(scan 预览 / apply 执行,支持 book 强制归并与 files 精确导入) |
|
|
34
|
+
| `novel_style_pattern` | **(受 stylePattern 开关控制)** 句式模式分析:把句子分为陈述/环境/心理/对话/疑问/反问/感叹七类,输出占比、高频组合与按章节的压缩排列序列,用于模仿原文叙事节奏 |
|
|
41
35
|
|
|
42
36
|
## 安装(web profile)
|
|
43
37
|
|
|
44
38
|
```sh
|
|
45
|
-
dsh plugin --profile web add D:/
|
|
39
|
+
dsh plugin --profile web add D:/Deep\ Seek插件库/novel-writer
|
|
46
40
|
```
|
|
47
41
|
|
|
48
|
-
|
|
49
|
-
`dsh
|
|
50
|
-
宿主端注册新工具与 `/api/dsh-novel-writer/state` 路由,浏览器端挂载侧边栏「句式分析」开关。
|
|
42
|
+
或手动等价操作:在 profile 的 `package.json` 的 `dsh.profile.bundles` 中加入
|
|
43
|
+
`dsh-novel-writer`,并在 profile `node_modules` 中链接本包。安装后重启 web 应用生效。
|
|
51
44
|
|
|
52
45
|
## 配置
|
|
53
46
|
|
|
54
|
-
插件 config 支持 `root
|
|
47
|
+
插件 config 支持 `root`:章节库根目录(默认取会话工作区,即 `novels/` 所在位置)。
|
|
48
|
+
在 profile 的 `cordis.patch.yml` 中可覆盖(顶层数组元素直接是条目,无需 `patch:` 包装):
|
|
55
49
|
|
|
56
50
|
```yaml
|
|
57
|
-
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
root: 'D:/我的小说库'
|
|
61
|
-
sentenceAnalysis:
|
|
62
|
-
enabled: true # 默认启用(UI 开关优先于此处)
|
|
63
|
-
autoAnalyze: true # 默认自动附带句式分析
|
|
51
|
+
- id: novel-writer
|
|
52
|
+
config:
|
|
53
|
+
root: 'D:/我的小说库'
|
|
64
54
|
```
|
|
65
55
|
|
|
66
|
-
|
|
56
|
+
### stylePattern 开关(句式模式仿写拓展)
|
|
67
57
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
- **新增**:novel_sentence_config 工具,与 UI 开关双向同步;
|
|
72
|
-
- **新增**:宿主端 `/api/dsh-novel-writer/state` 路由(loopback 围栏);
|
|
73
|
-
- 更新 SKILL.md / 系统提示词中的句式分析工作流。
|
|
58
|
+
`stylePattern`(布尔,**默认 false 关闭**):控制 `novel_style_pattern` 工具与
|
|
59
|
+
"句式模式仿写"提示词——分析原文陈述/反问/心理/对话等句子的排列节奏,引导续写时保持相近
|
|
60
|
+
叙事节奏。
|
|
74
61
|
|
|
75
|
-
|
|
76
|
-
|
|
62
|
+
> ⚠️ **已知风险**:该功能可能让整体文风变得更僵硬(机械套用句式模板)。默认关闭;
|
|
63
|
+
> 开启后模型侧也内置了"模式是参考、僵硬时优先自然表达"的约束,但仍建议按需使用。
|
|
77
64
|
|
|
78
|
-
|
|
79
|
-
-
|
|
65
|
+
**Web 设置开关(推荐)**:重启 web 后,打开 **设置 > 插件配置**,会看到
|
|
66
|
+
「小说写作助手 novel-writer」卡片,勾选「开启句式模式仿写(stylePattern)」即可——
|
|
67
|
+
改动写入 `$DSH_HOME/novel-writer.json`,**即时生效,无需重启**(工具未开启时调用会返回明确提示)。
|
|
68
|
+
|
|
69
|
+
也可在 profile 的 `cordis.patch.yml` 中配置(顶层数组元素直接是条目):
|
|
70
|
+
|
|
71
|
+
```yaml
|
|
72
|
+
- id: novel-writer
|
|
73
|
+
config:
|
|
74
|
+
root: ''
|
|
75
|
+
stylePattern: true
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
开关判定优先级:`$DSH_HOME/novel-writer.json` 中的持久化值 或 loader 配置的 `stylePattern`,任一为 true 即开启。
|
package/client.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dsh-novel-writer 客户端设置卡片。
|
|
3
|
+
*
|
|
4
|
+
* 注册进官方设置页的「插件配置」槽位(settings.plugin.item),提供
|
|
5
|
+
* stylePattern(句式模式仿写)开关。读写走宿主端的 /novel-writer-config
|
|
6
|
+
* 同源路由,绕开 rc.6 的 settings namespace 白名单限制;改动即时生效。
|
|
7
|
+
*
|
|
8
|
+
* 格式说明(与官方客户端插件一致):
|
|
9
|
+
* - window.__ModuleLoader__.load({ id: <包名>, factory })
|
|
10
|
+
* - factory 返回 { name, inject, apply } —— inject 声明本插件使用的服务名
|
|
11
|
+
* (缺少 inject 声明会导致 ctx.locale / ctx.slots 等被服务门禁拦截)。
|
|
12
|
+
*/
|
|
13
|
+
window.__ModuleLoader__.load({
|
|
14
|
+
id: "dsh-novel-writer",
|
|
15
|
+
factory: (require) => {
|
|
16
|
+
const React = require("react");
|
|
17
|
+
const { createElement: h, useEffect, useState } = React;
|
|
18
|
+
|
|
19
|
+
const name = "novel-writer-config";
|
|
20
|
+
const inject = ["slots"];
|
|
21
|
+
|
|
22
|
+
function NovelWriterConfigCard() {
|
|
23
|
+
const [enabled, setEnabled] = useState(null);
|
|
24
|
+
const [busy, setBusy] = useState(false);
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
let alive = true;
|
|
27
|
+
fetch("/novel-writer-config", { method: "GET" })
|
|
28
|
+
.then((r) => r.json())
|
|
29
|
+
.then((j) => { if (alive) setEnabled(j.stylePattern === true); })
|
|
30
|
+
.catch(() => { if (alive) setEnabled(false); });
|
|
31
|
+
return () => { alive = false; };
|
|
32
|
+
}, []);
|
|
33
|
+
const toggle = (next) => {
|
|
34
|
+
setBusy(true);
|
|
35
|
+
fetch("/novel-writer-config", {
|
|
36
|
+
method: "POST",
|
|
37
|
+
headers: { "Content-Type": "application/json" },
|
|
38
|
+
body: JSON.stringify({ stylePattern: next })
|
|
39
|
+
})
|
|
40
|
+
.then((r) => r.json())
|
|
41
|
+
.then((j) => setEnabled(j.stylePattern === true))
|
|
42
|
+
.catch(() => {})
|
|
43
|
+
.finally(() => setBusy(false));
|
|
44
|
+
};
|
|
45
|
+
return h("div", { style: { padding: "12px 0", borderBottom: "1px solid var(--dsw-alias-border-l2, #e5e7eb)" } },
|
|
46
|
+
h("div", { style: { fontWeight: 600 } }, "小说写作助手 novel-writer"),
|
|
47
|
+
h("div", { style: { color: "var(--dsw-alias-text-l2, #888)", fontSize: 12, margin: "4px 0 8px" } },
|
|
48
|
+
"句式模式仿写:分析原文陈述/反问/心理/对话等句子的排列节奏来模仿文风。⚠️ 可能让文风变僵硬,默认关闭;改动即时生效。"),
|
|
49
|
+
h("label", { style: { display: "flex", alignItems: "center", gap: 8, cursor: "pointer" } },
|
|
50
|
+
h("input", {
|
|
51
|
+
type: "checkbox",
|
|
52
|
+
checked: enabled === true,
|
|
53
|
+
disabled: busy || enabled === null,
|
|
54
|
+
onChange: (e) => toggle(e.target.checked)
|
|
55
|
+
}),
|
|
56
|
+
h("span", null, "开启句式模式仿写(stylePattern)")
|
|
57
|
+
)
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function apply(ctx) {
|
|
62
|
+
ctx.slots.inject("settings.plugin.item", () => ctx.slots.register({
|
|
63
|
+
name: "settings.plugin.item",
|
|
64
|
+
id: "novel-writer-config",
|
|
65
|
+
order: 105,
|
|
66
|
+
inject: () => ({})
|
|
67
|
+
}, NovelWriterConfigCard));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return { name, inject, apply };
|
|
71
|
+
}
|
|
72
|
+
});
|
package/cordis.patch.yml
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
# dsh-novel-writer bundle patch: mounts the novel-writing assistant plugin
|
|
2
|
-
# into the profile's loader tree. The entry's name is the plugin package
|
|
2
|
+
# into the profile's loader tree. The entry's `name` is the plugin package
|
|
3
3
|
# itself, resolved from the profile's node_modules.
|
|
4
|
-
#
|
|
5
|
-
# v0.3.0: the same row now carries BOTH halves — the node half (exports ".")
|
|
6
|
-
# runs in the host process (novel_* tools + /api/dsh-novel-writer/state
|
|
7
|
-
# routes for the UI switch), and the dsh.client declaration in package.json
|
|
8
|
-
# makes the browser half (exports "./client") load in the web GUI, mounting
|
|
9
|
-
# the 「句式分析」 sidebar entry with the enable switch.
|
|
10
4
|
- insert:
|
|
11
5
|
- id: novel-writer
|
|
12
6
|
name: 'dsh-novel-writer'
|