dsh-novel-writer 4.1.1 → 4.3.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.en.md +112 -23
- package/README.md +12 -2
- package/cordis.patch.yml +2 -2
- package/lib/analysis.js +266 -110
- package/lib/client.js +256 -80
- package/lib/core.js +197 -47
- package/lib/embedding.js +23 -8
- package/lib/index.js +331 -71
- package/lib/lexicons/markers.js +5 -2
- package/lib/style-metrics.js +251 -66
- package/lib/update-check.js +100 -20
- package/lib/vibe.js +236 -68
- package/mcp/README.md +86 -19
- package/mcp/server.mjs +335 -38
- package/package.json +4 -4
- package/server.json +36 -2
- package/skills/novel-writing/SKILL.md +6 -0
- package/smithery.yaml +30 -0
package/README.en.md
CHANGED
|
@@ -7,49 +7,97 @@ English | [中文](./README.md)
|
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
[](https://nodejs.org)
|
|
9
9
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
10
|
+
[](https://github.com/siweina/dsh-novel-writer/stargazers)
|
|
10
11
|
|
|
11
12
|
**16 tools that turn "my writing drifted" into numbers you can act on.**
|
|
12
13
|
Sentence, emotion and style-baseline analysis all run **on your machine**: a 24MB Chinese model ships with the package,
|
|
13
14
|
**zero API cost, your manuscript never leaves the device**. Built for DeepSeek Harness (DSH); the same engine is also
|
|
14
15
|
exposed as a **stdio MCP server** for Claude Desktop / Cursor.
|
|
15
16
|
|
|
17
|
+
[Install](#install) · [60-second start](#60-second-start) · [See the output](#see-the-output) · [The 16 tools](#provided-tools-16) · [MCP server](#mcp-server-usable-outside-dsh)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## What problem does it solve
|
|
22
|
+
|
|
23
|
+
| Your pain | What you get here |
|
|
24
|
+
|---|---|
|
|
25
|
+
| "This passage I just wrote doesn't sound like me" | **Six-metric style baseline**: μ±σ of the original measured per chapter across syntactic complexity / modifier density / abstraction / action density / hedging / gap index; a new chapter is compared dimension by dimension and flagged ⚠ when out of band |
|
|
26
|
+
| "The AI says my style changed but can't say where" | **Style check**: similarity score + a deviation list (which sentence types increased, how far sentence length drifted, whether the dominant emotion changed) |
|
|
27
|
+
| "Analysing a novel means paying for API calls" | Semantic search and emotion analysis run **fully local** — zero token cost |
|
|
28
|
+
| "I planted a plot thread and forgot to pay it off" | **Plot registry**: add / list / scan / done, automatically recording which chapters mention each thread |
|
|
29
|
+
| "Character settings contradict each other" | **Five settings tables + continuity audit** (bridge / OOC / outline drift) |
|
|
30
|
+
| "I can't read the report" | Everything is **tabulated numbers + quoted anchors from your own text** — screenshot-ready |
|
|
31
|
+
|
|
16
32
|
## Install
|
|
17
33
|
|
|
34
|
+
**Option 1: npm (recommended)**
|
|
35
|
+
|
|
18
36
|
```sh
|
|
19
37
|
dsh plugin --profile web add dsh-novel-writer
|
|
20
|
-
# or
|
|
21
|
-
npm install dsh-novel-writer
|
|
22
38
|
```
|
|
23
39
|
|
|
24
|
-
|
|
40
|
+
**Option 2: From GitHub**
|
|
25
41
|
|
|
26
|
-
|
|
42
|
+
```sh
|
|
43
|
+
dsh plugin --profile web add github:siweina/dsh-novel-writer#main
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Option 3: MCP (no DSH required)** — see [MCP server](#mcp-server-usable-outside-dsh)
|
|
47
|
+
|
|
48
|
+
Requires **Node >= 22.3**. After installing, **restart the web app**; a 「写作助手功能」 ("Writing Assistant") panel
|
|
49
|
+
appears in the sidebar.
|
|
50
|
+
|
|
51
|
+
## 60-second start
|
|
27
52
|
|
|
28
53
|
```sh
|
|
29
|
-
|
|
54
|
+
mkdir -p novels/my-novel # put chapter files inside (第01章.md, 第02章.md, …)
|
|
30
55
|
```
|
|
31
56
|
|
|
32
|
-
|
|
57
|
+
Then just ask in chat: **"run novel_style_report on my novel"** and you get:
|
|
33
58
|
|
|
34
|
-
|
|
59
|
+
```text
|
|
60
|
+
全书 1329 字:六维基线 μ=句法复杂度:2.3 修饰密度:35.6 抽象度:0.5 动作密度:101.7 不确定性:2.1 留白指数:7.0
|
|
61
|
+
推荐容差 25%/35%/100%…
|
|
62
|
+
```
|
|
35
63
|
|
|
36
|
-
|
|
64
|
+
(Report text is currently Chinese-only — see the note for non-Chinese users below.)
|
|
37
65
|
|
|
38
|
-
|
|
66
|
+
## See the output
|
|
39
67
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
68
|
+
**Style check** (new chapter vs. book baseline):
|
|
69
|
+
|
|
70
|
+
```text
|
|
71
|
+
相似度 0.946 · verdict: high
|
|
72
|
+
偏差清单:心理占比略多 · 对话占比略少 · 短句占比略少 · 主导情绪由 anger 变为 joy
|
|
73
|
+
fixAnchors:3 条原著锚段(对话 / 心理 / 描写各一条,供逐句对照修正)
|
|
44
74
|
```
|
|
45
75
|
|
|
46
|
-
**
|
|
76
|
+
**Semantic search** (natural language, local vectors):
|
|
47
77
|
|
|
48
|
-
```
|
|
49
|
-
|
|
78
|
+
```text
|
|
79
|
+
查询「与那盏没有点的灯有关的段落」→
|
|
80
|
+
第02章.md 0.619 对街那盏灯,亮了。
|
|
81
|
+
第01章.md 0.593 阿澈的目光越过老周的肩膀,落在对街那栋小楼上…
|
|
50
82
|
```
|
|
51
83
|
|
|
52
|
-
|
|
84
|
+
**Paragraph structure**: 34 paragraphs total (dialogue 5 / psychology 0 / mixed 15 / narration 14)
|
|
85
|
+
|
|
86
|
+
## Why not an online AI writing tool
|
|
87
|
+
|
|
88
|
+
| | This plugin | Online AI writing tools | Generic text-analysis libraries |
|
|
89
|
+
|---|---|---|---|
|
|
90
|
+
| Does the manuscript leave the device | **No** | Yes | Depends |
|
|
91
|
+
| Cost | **0 (local inference)** | Billed per token | Self-hosted |
|
|
92
|
+
| Purpose-built for Chinese fiction | **Yes** | Generic | No |
|
|
93
|
+
| Style baseline (μ±σ) | **Yes** | Rare | No |
|
|
94
|
+
| DSH integration | **16 tools + sidebar toggles** | None | None |
|
|
95
|
+
| Usable without DSH | **Yes (MCP)** | Yes | You wrap it yourself |
|
|
96
|
+
|
|
97
|
+
> **A note for non-Chinese users**: this plugin is designed for analysing and writing Chinese fiction — the sentence-pattern,
|
|
98
|
+
> emotion and imagery engines, and the bundled semantic model, are all built and tuned for Chinese corpora, and the report
|
|
99
|
+
> text itself is Chinese. Covering English and other languages *while* going deep on Chinese is genuinely beyond my current
|
|
100
|
+
> ability. I'm sorry for the inconvenience and hope you understand.
|
|
53
101
|
|
|
54
102
|
---
|
|
55
103
|
|
|
@@ -62,7 +110,7 @@ After installing, **restart the web app** to activate (host registers 16 tools +
|
|
|
62
110
|
5. **Emotion purification & quantification**: strong/weak emotion-word grading, pollution detection, caveat warning + AI re-verification; Valence sliding window → variance V / delta Δ / conflict index C + implicit imagery carriers.
|
|
63
111
|
6. **Worldview & pragmatics detection**: auto cultural-baseline detection with confidence; speechStyle title/honorifics/rituals/tone norms; genre & theme + webnovel signals.
|
|
64
112
|
7. **Writing toolkit**: plot tracking / five settings tables (characters·locations·items·timeline·worldview) / chapter summaries / continuity audit / batch import / style check / continuation writing.
|
|
65
|
-
8. **Per-tool UI toggles**: "Writing Assistant" sidebar panel (master + grouped tool toggles + feature toggles), plain-language labels, data-dir usage & semantic-engine status display.
|
|
113
|
+
8. **Per-tool UI toggles**: 「写作助手功能」 ("Writing Assistant") sidebar panel (master + grouped tool toggles + feature toggles), plain-language labels, data-dir usage & semantic-engine status display.
|
|
66
114
|
9. **Style Baseline**: Six writing metrics (syntactic complexity / modifier density / abstraction / action density / hedging / gap index) + per-chapter μ±σ baseline band; `novel_style_report` outputs the band, `novel_style_check` compares new chapters (in-band ✓ / out-of-band ⚠); per-metric ±% tolerance configurable in the sidebar (**recommended = 1.5× σ of the book's chapter variance**, rounded, clamped to ±10%~100%; leave blank to use recommended) — free theme, writing style kept inside the band.
|
|
67
115
|
10. **Writing sentinels**: `novel_continuity_check` extended — ①**bridge check** (`chapter`: time jumps / semantic distance / character continuity / hook handoff, with quoted evidence) ②**OOC check** (`ooc`: per-character emotion baseline deviation) ③**outline drift** (`outline`: direction vs body keyword overlap); **brief mode** for report tools.
|
|
68
116
|
11. **Original mode & creation files**: fill in creation settings in the sidebar (worldview/characters/forbidden/main conflict/genre/extras, blank = model decides, per-book profile library); novel_outline maintains creation files (bible/characters/outline/hooks/status), enforcing the bible → outline → hook chain with dynamic batches (10→20→30 chapters) to prevent plot jumps and OOC.
|
|
@@ -93,6 +141,37 @@ After installing, **restart the web app** to activate (host registers 16 tools +
|
|
|
93
141
|
|
|
94
142
|
---
|
|
95
143
|
|
|
144
|
+
## MCP server (usable outside DSH)
|
|
145
|
+
|
|
146
|
+
The package ships a **stdio MCP server** (`mcp/server.mjs`) that exposes all 16 tools to any MCP client,
|
|
147
|
+
e.g. Claude Desktop or Cursor. **It runs as a local process on your own machine — no server, no network, no daemon.**
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
npx -y -p dsh-novel-writer dsh-novel-writer-mcp --root /path/to/your/novels
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Client config example (`claude_desktop_config.json` / Cursor `mcp.json`):
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"mcpServers": {
|
|
158
|
+
"dsh-novel-writer": {
|
|
159
|
+
"command": "npx",
|
|
160
|
+
"args": ["-y", "-p", "dsh-novel-writer", "dsh-novel-writer-mcp", "--root", "/path/to/your/novels"]
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
> The package name (`dsh-novel-writer`) and the bin name (`dsh-novel-writer-mcp`) differ, so `npx -y dsh-novel-writer`
|
|
167
|
+
> will **not** start the MCP server — always pass `-p dsh-novel-writer dsh-novel-writer-mcp`.
|
|
168
|
+
|
|
169
|
+
Library-root priority: `--root` > env `DSH_NOVEL_WRITER_ROOT` > current working directory.
|
|
170
|
+
`root` arguments must stay inside the configured root, and `novel_import`'s `src` is restricted to it as well unless you
|
|
171
|
+
start the server with `--allow-external-src`. Details: [mcp/README.md](./mcp/README.md).
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
96
175
|
## Configuration
|
|
97
176
|
|
|
98
177
|
```yaml
|
|
@@ -123,13 +202,23 @@ Under `<library-root>/.novel-writer/`: `plots` / `settings` / `summaries` / `ana
|
|
|
123
202
|
|
|
124
203
|
**Permissions and external services**:
|
|
125
204
|
|
|
126
|
-
- Filesystem:
|
|
127
|
-
|
|
128
|
-
|
|
205
|
+
- Filesystem: reads/writes the user-chosen library root (`novels/`) and its data directory (`<root>/.novel-writer/`),
|
|
206
|
+
plus the plugin state file (`~/.dsh/dsh-novel-writer/state.json`). **One exception**: `novel_import`'s `src` is by design
|
|
207
|
+
allowed to point anywhere (that is how you import an old manuscript from elsewhere), and `mode:"apply"` + `move:true`
|
|
208
|
+
**deletes the source files** — the scope of the deletion is decided by the caller, so only point it at a directory whose
|
|
209
|
+
contents you know.
|
|
210
|
+
- Built-in skill: registers its own `novel-writing` skill through `ctx.skills` (since v4.3.0); it only reads the packaged
|
|
211
|
+
`skills/novel-writing/SKILL.md`, **writes to no skill directory** and needs no host configuration; hosts without a `skills`
|
|
212
|
+
service are skipped silently.
|
|
213
|
+
- Local HTTP: registers 5 routes inside the DSH Web GUI (state / reveal / reports / demo / update-check), loopback-only;
|
|
214
|
+
`allowLanState` defaults to off, so LAN access is denied by default.
|
|
215
|
+
- MCP server (`mcp/server.mjs`): the `root` argument of every tool must fall inside the library root given to `--root`
|
|
216
|
+
(out-of-root values are rejected and fall back); `novel_import`'s `src` is likewise root-limited unless you explicitly
|
|
217
|
+
opt out with `--allow-external-src` (since v4.3.0).
|
|
129
218
|
- Network: the only outbound call is the GitHub Releases API (`api.github.com`) for update checks —
|
|
130
219
|
3s timeout, 24h cache, silent fallback; no manuscript content is sent.
|
|
131
|
-
- Subprocesses: none, except opening the OS file manager with
|
|
132
|
-
- Lifecycle scripts: none.
|
|
220
|
+
- Subprocesses: none, except opening the OS file manager with a plain argv array (no shell).
|
|
221
|
+
- Lifecycle scripts: none (no preinstall / postinstall / prepare).
|
|
133
222
|
|
|
134
223
|
**Failure bounds**: semantic engine failure falls back to pure rule mode; cache/disk failures never block
|
|
135
224
|
tool results; a plugin load failure cannot affect the DSH host process.
|
package/README.md
CHANGED
|
@@ -191,10 +191,20 @@ npx -y -p dsh-novel-writer dsh-novel-writer-mcp --root /你的小说库路径
|
|
|
191
191
|
|
|
192
192
|
**权限与外部服务**:
|
|
193
193
|
|
|
194
|
-
-
|
|
195
|
-
以及插件自身的开关文件 `~/.dsh/dsh-novel-writer/state.json
|
|
194
|
+
- 文件系统:读写用户指定的书库根目录 `novels/` 与其数据目录 `<root>/.novel-writer/`,
|
|
195
|
+
以及插件自身的开关文件 `~/.dsh/dsh-novel-writer/state.json`。**例外一处**:`novel_import` 的 `src`
|
|
196
|
+
按设计可以指向任意目录(用于把别处的旧稿导入书库),`mode:"apply"` + `move:true` 会**删除源文件**——
|
|
197
|
+
删改范围由调用方决定,请只在明确知道源目录内容时使用。**例外仅此一处**:MCP 服务器默认把这个 `src`
|
|
198
|
+
也限制在书库根内(见下方 MCP 一节)。
|
|
199
|
+
- 内置技能:通过 `ctx.skills` 注册自带 `novel-writing` 技能(v4.3.0 起),只读取包内
|
|
200
|
+
`skills/novel-writing/SKILL.md`,**不写入任何技能目录**、不需要改宿主配置;宿主没有 `skills` 服务时静默跳过。
|
|
196
201
|
- 本地 HTTP:在 DSH Web GUI 内注册 5 条路由(state / reveal / reports / demo / update-check),
|
|
197
202
|
仅回环地址可访问;`allowLanState` 默认关闭,局域网访问默认拒绝。
|
|
203
|
+
- MCP 服务器(`mcp/server.mjs`):工具参数里的 `root` 必须落在启动时 `--root` 指定的书库根之内,
|
|
204
|
+
越界会被拒绝并回退;`novel_import` 的 `src` 默认也限根内,确需导入外部目录时用
|
|
205
|
+
`--allow-external-src` 显式放开(v4.3.0 起)。单行报文上限 4 MiB,超限整行丢弃;stderr 默认只记一行错误摘要,
|
|
206
|
+
不回显正文与堆栈(需要完整堆栈用 `DEBUG=1`);长任务可用 `notifications/cancelled` 取消。详见
|
|
207
|
+
[mcp/README.md 第 0 节](./mcp/README.md#0-安全边界v420-起)。
|
|
198
208
|
- 外部网络:唯一外呼是 GitHub Releases API(`api.github.com`)检查新版本——3 秒超时、24 小时缓存、
|
|
199
209
|
失败静默降级;请求不含任何书籍内容。
|
|
200
210
|
- 子进程:无。唯一例外是打开系统文件管理器(Windows `explorer` / macOS `open` / Linux `xdg-open`),
|
package/cordis.patch.yml
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# dsh-novel-writer v4.
|
|
1
|
+
# dsh-novel-writer v4.3.0 bundle patch: 16 tools (incl. novel_semantic_search) + local embedding engine.
|
|
2
2
|
# dsh-novel-writer bundle patch: mounts the novel-writing assistant plugin
|
|
3
3
|
# into the profile's loader tree. The entry's name is the plugin package
|
|
4
4
|
# itself, resolved from the profile's node_modules.
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
# runs in the host process (novel_* tools + /api/dsh-novel-writer/state
|
|
8
8
|
# routes for the UI switch), and the dsh.client declaration in package.json
|
|
9
9
|
# makes the browser half (exports "./client") load in the web GUI, mounting
|
|
10
|
-
# the
|
|
10
|
+
# the 「写作助手功能」 sidebar entry with the enable switch.
|
|
11
11
|
- insert:
|
|
12
12
|
- id: novel-writer
|
|
13
13
|
name: 'dsh-novel-writer'
|