@waterwx/dsh-novel-forge 1.2.0 → 1.2.1-alpha

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.
Files changed (125) hide show
  1. package/README.md +237 -349
  2. package/lib/client.js +54447 -10560
  3. package/lib/index.js +12008 -5071
  4. package/lib/types/action-guard.d.ts +61 -0
  5. package/lib/types/ai-scan.d.ts +36 -0
  6. package/lib/types/assets.d.ts +18 -3
  7. package/lib/types/assistant.d.ts +29 -0
  8. package/lib/types/author-assets.d.ts +25 -0
  9. package/lib/types/bookshelf.d.ts +11 -1
  10. package/lib/types/client/api.d.ts +147 -9
  11. package/lib/types/client/docx.d.ts +2 -0
  12. package/lib/types/client/index.d.ts +1 -1
  13. package/lib/types/client/llmLive.d.ts +33 -0
  14. package/lib/types/client/locales.d.ts +28 -11
  15. package/lib/types/client/panel/AdaptModeView.d.ts +5 -0
  16. package/lib/types/client/panel/AiTag.d.ts +1 -0
  17. package/lib/types/client/panel/AssistantTab.d.ts +4 -1
  18. package/lib/types/client/panel/AuthorAssetsView.d.ts +4 -0
  19. package/lib/types/client/panel/AuthorHome.d.ts +34 -0
  20. package/lib/types/client/panel/BookAnalysisView.d.ts +4 -0
  21. package/lib/types/client/panel/CmdPalette.d.ts +12 -0
  22. package/lib/types/client/panel/CreateBookView.d.ts +5 -1
  23. package/lib/types/client/panel/DirectorView.d.ts +7 -0
  24. package/lib/types/client/panel/GlobalAssetLibraryView.d.ts +4 -0
  25. package/lib/types/client/panel/IdeaInspirationView.d.ts +6 -0
  26. package/lib/types/client/panel/ImportModal.d.ts +7 -0
  27. package/lib/types/client/panel/KnowledgeBaseView.d.ts +4 -0
  28. package/lib/types/client/panel/LiveFeedLog.d.ts +8 -0
  29. package/lib/types/client/panel/MarketRadarView.d.ts +5 -0
  30. package/lib/types/client/panel/ModelManager.d.ts +14 -0
  31. package/lib/types/client/panel/NovelPanel.d.ts +6 -1
  32. package/lib/types/client/panel/PageHeader.d.ts +18 -0
  33. package/lib/types/client/panel/ProgressConsole.d.ts +17 -0
  34. package/lib/types/client/panel/ProgressHomeView.d.ts +5 -0
  35. package/lib/types/client/panel/ReasoningSection.d.ts +10 -0
  36. package/lib/types/client/panel/SettingsView.d.ts +19 -0
  37. package/lib/types/client/panel/ShelfView.d.ts +12 -1
  38. package/lib/types/client/panel/SubPage.d.ts +27 -0
  39. package/lib/types/client/panel/toast.d.ts +2 -0
  40. package/lib/types/client/panel/views.d.ts +25 -7
  41. package/lib/types/client/run-status.d.ts +19 -0
  42. package/lib/types/client/text.d.ts +9 -0
  43. package/lib/types/docx-core.d.ts +16 -0
  44. package/lib/types/docx.d.ts +2 -3
  45. package/lib/types/engine.d.ts +146 -40
  46. package/lib/types/global-assets.d.ts +6 -0
  47. package/lib/types/index.d.ts +18 -2
  48. package/lib/types/llm-live.d.ts +44 -0
  49. package/lib/types/market-radar-scan.d.ts +19 -0
  50. package/lib/types/market-radar-sources.d.ts +31 -0
  51. package/lib/types/migrate-output.d.ts +25 -0
  52. package/lib/types/novel-context.d.ts +80 -0
  53. package/lib/types/prompt-utils.d.ts +35 -0
  54. package/lib/types/prompting.d.ts +10 -0
  55. package/lib/types/protocol.d.ts +1029 -123
  56. package/lib/types/review-policy.d.ts +97 -0
  57. package/lib/types/routes.d.ts +4 -0
  58. package/lib/types/run.d.ts +3 -1
  59. package/lib/types/stage-contract.d.ts +60 -0
  60. package/package.json +51 -27
  61. package/scripts/patch-schemastery.mjs +47 -0
  62. package/src/action-guard.ts +127 -0
  63. package/src/ai-scan.ts +179 -0
  64. package/src/assets.ts +1774 -520
  65. package/src/assistant.ts +1082 -770
  66. package/src/author-assets.ts +149 -0
  67. package/src/bookshelf.ts +187 -151
  68. package/src/client/api.ts +684 -410
  69. package/src/client/docx.ts +37 -69
  70. package/src/client/index.ts +3 -1
  71. package/src/client/llmLive.ts +101 -0
  72. package/src/client/locales.ts +418 -383
  73. package/src/client/mount.tsx +1 -1
  74. package/src/client/panel/AdaptModeView.tsx +535 -0
  75. package/src/client/panel/AiTag.tsx +7 -0
  76. package/src/client/panel/AssetsTab.tsx +448 -458
  77. package/src/client/panel/AssistantTab.tsx +355 -301
  78. package/src/client/panel/AuthorAssetsView.tsx +206 -0
  79. package/src/client/panel/AuthorHome.tsx +309 -0
  80. package/src/client/panel/BookAnalysisView.tsx +63 -0
  81. package/src/client/panel/CmdPalette.tsx +102 -0
  82. package/src/client/panel/CreateBookView.tsx +366 -348
  83. package/src/client/panel/DirectorView.tsx +200 -0
  84. package/src/client/panel/GlobalAssetLibraryView.tsx +168 -0
  85. package/src/client/panel/IdeaInspirationView.tsx +76 -0
  86. package/src/client/panel/ImportModal.tsx +303 -0
  87. package/src/client/panel/KnowledgeBaseView.tsx +125 -0
  88. package/src/client/panel/LiveFeedLog.tsx +67 -0
  89. package/src/client/panel/MarketRadarView.tsx +377 -0
  90. package/src/client/panel/ModelManager.tsx +205 -0
  91. package/src/client/panel/NovelPanel.tsx +5403 -4597
  92. package/src/client/panel/PageHeader.tsx +37 -0
  93. package/src/client/panel/ProgressConsole.tsx +63 -0
  94. package/src/client/panel/ReaderView.tsx +306 -306
  95. package/src/client/panel/ReasoningSection.tsx +31 -0
  96. package/src/client/panel/RunPanel.tsx +223 -204
  97. package/src/client/panel/SettingsView.tsx +305 -0
  98. package/src/client/panel/ShelfView.tsx +266 -236
  99. package/src/client/panel/SubPage.tsx +42 -0
  100. package/src/client/panel/WorldTab.tsx +202 -202
  101. package/src/client/panel/panel.module.css +5764 -2941
  102. package/src/client/panel/toast.ts +51 -0
  103. package/src/client/panel/views.tsx +401 -314
  104. package/src/client/run-status.ts +143 -0
  105. package/src/client/sidebar-entry.ts +1 -1
  106. package/src/client/text.ts +28 -0
  107. package/src/docx-core.ts +53 -0
  108. package/src/docx.ts +44 -83
  109. package/src/engine.ts +4231 -2787
  110. package/src/global-assets.ts +59 -0
  111. package/src/index.ts +311 -252
  112. package/src/llm-live.ts +68 -0
  113. package/src/market-radar-scan.ts +41 -0
  114. package/src/market-radar-sources.ts +173 -0
  115. package/src/migrate-output.ts +76 -0
  116. package/src/novel-context.ts +286 -0
  117. package/src/prompting.ts +26 -0
  118. package/src/protocol.ts +2072 -1182
  119. package/src/review-policy.ts +161 -0
  120. package/src/routes.ts +3405 -2151
  121. package/src/run.ts +342 -330
  122. package/src/stage-contract.ts +189 -0
  123. package/lib/client.js.map +0 -1
  124. package/lib/index.js.map +0 -1
  125. package/src/client/panel/BookshelfBar.tsx +0 -170
package/src/protocol.ts CHANGED
@@ -1,1182 +1,2072 @@
1
- /**
2
- * dsh-novel-forge — shared protocol between the host half (Node) and the
3
- * browser half (web GUI). Route paths, request/response shapes, the project
4
- * state file format, and the NDJSON generation stream frames all live here so
5
- * both halves spell exactly one vocabulary.
6
- */
7
-
8
- /** The /api/dsh-novel-forge route family (same-origin, loopback-fenced). */
9
- export const NOVEL_API = {
10
- status: '/api/dsh-novel-forge/status',
11
- loadOutline: '/api/dsh-novel-forge/load-outline',
12
- saveOutline: '/api/dsh-novel-forge/save-outline',
13
- plan: '/api/dsh-novel-forge/plan',
14
- volumes: '/api/dsh-novel-forge/volumes',
15
- bible: '/api/dsh-novel-forge/bible',
16
- assets: '/api/dsh-novel-forge/assets',
17
- styleEngine: '/api/dsh-novel-forge/style-engine',
18
- generate: '/api/dsh-novel-forge/generate',
19
- review: '/api/dsh-novel-forge/review',
20
- rewrite: '/api/dsh-novel-forge/rewrite',
21
- polish: '/api/dsh-novel-forge/polish',
22
- /** 采纳待确认草稿(润色/重写产物)覆盖正文文件。 */
23
- draftApply: '/api/dsh-novel-forge/draft/apply',
24
- /** 放弃待确认草稿,保留原稿。 */
25
- draftDiscard: '/api/dsh-novel-forge/draft/discard',
26
- summary: '/api/dsh-novel-forge/summary',
27
- foreshadow: '/api/dsh-novel-forge/foreshadow',
28
- exportBook: '/api/dsh-novel-forge/export',
29
- chapter: '/api/dsh-novel-forge/chapter',
30
- /** 审查任意正文文本(作者手动编辑后,不落盘)。 */
31
- chapterCheck: '/api/dsh-novel-forge/chapter/check',
32
- /** 保存手动编辑的正文(自动备份 .bak)。 */
33
- chapterSave: '/api/dsh-novel-forge/chapter/save',
34
- assistant: '/api/dsh-novel-forge/assistant',
35
- assistantHistory: '/api/dsh-novel-forge/assistant-history',
36
- /** 清空助手对话记录。 */
37
- assistantClear: '/api/dsh-novel-forge/assistant/clear',
38
- bookshelf: '/api/dsh-novel-forge/bookshelf',
39
- /** 重置项目(可选携带新大纲):清空设定/卷/章节/伏笔/资产/事实库。 */
40
- reset: '/api/dsh-novel-forge/reset',
41
- /** 全书一致性质检:LLM 扫描已生成章节,输出矛盾问题清单。 */
42
- audit: '/api/dsh-novel-forge/audit',
43
- /** 角色卡刷新:基于事实库与各章摘要聚合角色当前状态。 */
44
- charactersRefresh: '/api/dsh-novel-forge/characters/refresh',
45
- /** 事实库回填:对历史已生成章节批量抽取事实(旧章节无事实记录时用)。 */
46
- factsBackfill: '/api/dsh-novel-forge/facts/backfill',
47
- /** 设定圣经局部修补(如世界观规则编辑)。 */
48
- biblePatch: '/api/dsh-novel-forge/bible/patch',
49
- /** 小说简介:生成(AI)/补全(AI)/保存。 */
50
- blurb: '/api/dsh-novel-forge/blurb',
51
- /** 重命名当前书(同步项目与书架条目)。 */
52
- rename: '/api/dsh-novel-forge/rename',
53
- /** 大世界:AI 提炼 / 保存结构化数据(境界/区域/势力)。 */
54
- world: '/api/dsh-novel-forge/world',
55
- /** 封面:GET 读取(dataUrl)/ POST 上传或移除。 */
56
- cover: '/api/dsh-novel-forge/blurb/cover',
57
- /** 剧情线管理:增删改 + 关联章节。 */
58
- plotlines: '/api/dsh-novel-forge/plotlines',
59
- /** 角色库:AI 提炼 / 采纳 / 更新 / 删除。 */
60
- roles: '/api/dsh-novel-forge/roles',
61
- /** 作者复盘补跑:对已写章节补齐 authorReview(全书流式 / 单章 JSON)。 */
62
- reviewBackfill: '/api/dsh-novel-forge/review/backfill',
63
- /** 章节复位:generating 卡死 → pending(可重新生成)。 */
64
- chapterReset: '/api/dsh-novel-forge/chapter/reset',
65
- /** 章节直接通过:作者对 rejected/written 章节行使最终决定权。 */
66
- chapterApprove: '/api/dsh-novel-forge/chapter/approve',
67
- /** 敏感词检查:全书已写章节或指定文本。 */
68
- sensitiveCheck: '/api/dsh-novel-forge/sensitive-check',
69
- /** 开书想法 → AI 补全大纲:输入一句话想法,生成 2-3 个可选大纲方案。 */
70
- outlineSuggest: '/api/dsh-novel-forge/outline/suggest',
71
- /** 拆书分析:对已写章节做结构/人物/文风/卖点四维体检(两阶段:源笔记→分节分析)。 */
72
- breakdown: '/api/dsh-novel-forge/breakdown',
73
- /** 漫剧分镜生成:章节 → 角色锚点 + 分镜表(可适配豆包/Seedance/SD)。 */
74
- storyboard: '/api/dsh-novel-forge/storyboard',
75
- /** 漫剧分集计划:读一卷 → 按故事弧线分集(高潮拆集/过渡并章)。 */
76
- storyboardPlan: '/api/dsh-novel-forge/storyboard/plan',
77
- /** 生产单:启动批量生产(计划补足 + 逐章生成 + 被拒分级处理)。 */
78
- runStart: '/api/dsh-novel-forge/run/start',
79
- /** 生产单控制:pause / resume / stop。 */
80
- runControl: '/api/dsh-novel-forge/run/control',
81
- /** 生产单状态(含进度统计与日志)。 */
82
- runStatus: '/api/dsh-novel-forge/run/status',
83
- config: '/api/dsh-novel-forge/config',
84
- openFolder: '/api/dsh-novel-forge/open-folder',
85
- } as const
86
-
87
- /** 书架:一本书的条目。 */
88
- export interface BookEntry {
89
- /** 稳定 id。 */
90
- id: string
91
- /** 书名。 */
92
- bookName: string
93
- /** 该书输出目录(独立项目目录)。 */
94
- outputDir: string
95
- /** 创建时间。 */
96
- createdAt: string
97
- /** 最后活动时间。 */
98
- updatedAt: string
99
- }
100
-
101
- /** 书架快照(含每本书的进度摘要)。 */
102
- export interface BookshelfSnapshot {
103
- books: Array<BookEntry & { done: number; total: number; hasProject: boolean; hasCover: boolean; blurb?: string }>
104
- /** 当前激活的书 id(无则 null)。 */
105
- activeBookId: string | null
106
- }
107
-
108
- /** POST /bookshelf 请求:创建新书。 */
109
- export interface BookCreateRequest {
110
- bookName: string
111
- outputDir?: string
112
- /** 开书向导:创建时直接导入的大纲文本(提供则立即建立项目)。 */
113
- outline?: string
114
- }
115
-
116
- /** POST /reset 请求:重置项目(可选更新大纲)。 */
117
- export interface ResetRequest {
118
- /** 新大纲文本;提供则替换 outline,否则保留原大纲。 */
119
- outline?: string
120
- }
121
-
122
- /** POST /bookshelf/activate 请求:切换当前书。 */
123
- export interface BookActivateRequest {
124
- id: string
125
- }
126
-
127
- /** POST /bookshelf/remove 请求:移除书架条目。 */
128
- export interface BookRemoveRequest {
129
- id: string
130
- }
131
-
132
- /** Chapter lifecycle states (the writing pipeline's state machine). */
133
- export type ChapterStatus =
134
- | 'pending' // planned, not started
135
- | 'generating' // LLM writing right now
136
- | 'written' // body on disk, awaiting review
137
- | 'reviewing' // review in progress
138
- | 'approved' // passed review (or user-approved)
139
- | 'rejected' // review found problems
140
- | 'error' // generation failed
141
-
142
- /** One chapter in the plan. */
143
- export interface ChapterPlan {
144
- /** 1-based chapter number (stable identity; files are named from it). */
145
- no: number
146
- /** Volume this chapter belongs to (1-based; 0 = unassigned). */
147
- volume: number
148
- /** Chapter title, decided by the LLM plan step. */
149
- title: string
150
- /** Story beats / plot points for this chapter (model-facing guidance). */
151
- beats: string
152
- /** Target character count (defaults to the configured chapter size). */
153
- targetChars: number
154
- /** Generation/review state. */
155
- status: ChapterStatus
156
- /** 进入 generating 的时间(用于超时自动复位;未在生成时无此字段)。 */
157
- generatingAt?: string
158
- /** Actual character count once generated. */
159
- chars?: number
160
- /** Failure message when status is 'error'. */
161
- error?: string
162
- /** Output file name once generated (relative to the output dir). */
163
- file?: string
164
- /** LLM summary of the chapter (narrative memory for later chapters). */
165
- summary?: string
166
- /** Latest review report (present once reviewed). */
167
- review?: ReviewReport
168
- /** 作者复盘:钩子兑现/结尾钩子/剧情线推进/连续性/节奏趋势(生成后自动)。 */
169
- authorReview?: AuthorReview
170
- /**
171
- * 待确认草稿:润色(去AI味)或整章重写的产物正文。生成时先存这里,
172
- * 用户看过对比后点「采纳」才覆盖正文文件;点「放弃」则丢弃。刷新页面不丢失。
173
- */
174
- pendingDraft?: string
175
- }
176
-
177
- /** 作者复盘:叙事结构层面的逐章检查(钩子/推进/连续性/趋势)。 */
178
- export interface AuthorReview {
179
- /** 上一章结尾钩子是否在本章兑现。 */
180
- hookHonored: boolean
181
- /** 钩子兑现说明(未兑现时给出建议)。 */
182
- hookNote: string
183
- /** 本章结尾钩子强度 0-10。 */
184
- endingHook: number
185
- /** 剧情线推进情况(推进了哪条线/或未推进)。 */
186
- plotlineProgress: string
187
- /** 结构化:本章推进的剧情线名称列表(与项目剧情线 name 精确匹配,复盘后自动关联章节)。 */
188
- advancedLines?: string[]
189
- /** 连续性检查(人物位置/时间/伤势/资源是否与上章衔接)。 */
190
- continuity: string
191
- /** 近期节奏趋势提示(拖沓/爽点密度等)。 */
192
- trend: string
193
- /** 复盘时间。 */
194
- reviewedAt: string
195
- }
196
-
197
- /** One review finding. */
198
- export interface ReviewIssue {
199
- /** Severity: high = must fix, medium = should fix, low = suggestion. */
200
- severity: 'high' | 'medium' | 'low'
201
- /** What the problem is. */
202
- item: string
203
- /** Concrete suggestion for fixing it. */
204
- suggestion: string
205
- }
206
-
207
- /** AI review report for one chapter. */
208
- export interface ReviewReport {
209
- /** Overall score 0-100. */
210
- score: number
211
- /** Pass threshold (config; 70 default). */
212
- passed: boolean
213
- /** One-line verdict. */
214
- verdict: string
215
- /** Individual findings. */
216
- issues: ReviewIssue[]
217
- /** When the review ran. */
218
- reviewedAt: string
219
- }
220
-
221
- /** A volume of the book. */
222
- export interface Volume {
223
- /** 1-based volume number. */
224
- no: number
225
- /** Volume title. */
226
- title: string
227
- /** Volume positioning / summary. */
228
- summary: string
229
- /** First chapter number of this volume. */
230
- chapterStart: number
231
- /** Last chapter number (inclusive). */
232
- chapterEnd: number
233
- }
234
-
235
- /** A character card from the story bible. */
236
- export interface CharacterCard {
237
- name: string
238
- role: 'protagonist' | 'supporting' | 'antagonist' | 'other'
239
- /** Personality / traits (short lines). */
240
- traits: string[]
241
- /** Goals and motivations. */
242
- goals: string
243
- /** Key relations to other characters. */
244
- relations: string
245
- /** 知情度:该角色已经知道的事实/秘密(未列出的信息该角色不知道)。 */
246
- knowledge?: string[]
247
- }
248
-
249
- /** The structured story bible (worldbuilding extracted from the outline). */
250
- export interface StoryBible {
251
- /** Genre + tone tags. */
252
- genre: string
253
- /** Worldbuilding rules (power system, geography, factions...). */
254
- worldRules: string[]
255
- /** Character cards. */
256
- characters: CharacterCard[]
257
- /** Writing red lines (forbidden content / must-avoid tropes). */
258
- redLines: string[]
259
- /** Style guidance (pacing, pov, tone). */
260
- style: string[]
261
- /** When the bible was generated. */
262
- generatedAt?: string
263
- }
264
-
265
- /** A planted/active/resolved foreshadowing thread. */
266
- export interface Foreshadow {
267
- /** Stable id. */
268
- id: string
269
- /** What the foreshadow is. */
270
- description: string
271
- /** Chapter where it was planted (undefined = planned). */
272
- plantedChapter?: number
273
- /** Chapter where it should be paid off. */
274
- targetChapter?: number
275
- /** Lifecycle state. */
276
- status: 'planned' | 'planted' | 'progressing' | 'resolved' | 'abandoned'
277
- /** Resolution note when resolved. */
278
- resolvedNote?: string
279
- }
280
-
281
- /** 一条已确立的叙事事实(事实库/时间线,注入后续章节生成)。 */
282
- export interface ChapterFact {
283
- /** 来源章节号。 */
284
- chapterNo: number
285
- /** 事实文本(人物状态/境界资源/关系变化/伏笔落地等)。 */
286
- text: string
287
- }
288
-
289
- /** 一条全书质检发现的问题(一致性矛盾,定位到章)。 */
290
- export interface AuditIssue {
291
- /** 问题所在章节号(无法定位时 0)。 */
292
- chapterNo: number
293
- severity: 'high' | 'medium' | 'low'
294
- /** 矛盾描述。 */
295
- item: string
296
- /** 修改建议。 */
297
- suggestion: string
298
- }
299
-
300
- /** POST /audit 响应。 */
301
- export interface AuditResponse {
302
- issues: AuditIssue[]
303
- /** 参与质检的章节数。 */
304
- auditedChapters: number
305
- /** 质检时间。 */
306
- auditedAt: string
307
- }
308
-
309
- /** 全书质检的实时状态(通过 /status 暴露给面板/外部读取)。 */
310
- export interface AuditStatus {
311
- status: 'idle' | 'running' | 'done' | 'error'
312
- /** 开始时间(ISO)。 */
313
- startedAt?: string
314
- /** 结束时间(ISO)。 */
315
- finishedAt?: string
316
- /** 总批次数(0 = 尚未开始/无章节)。 */
317
- totalBatches: number
318
- /** 已完成批次数。 */
319
- completedBatches: number
320
- /** 参与质检的章节数。 */
321
- auditedChapters?: number
322
- /** 发现的问题数(done 后有效)。 */
323
- issuesCount?: number
324
- /** 最近一次质检的问题清单(done 后有效;error 时为空)。 */
325
- issues?: AuditIssue[]
326
- /** 失败信息(error 时有效)。 */
327
- error?: string
328
- }
329
-
330
- /** 一条剧情线(主线/支线/人物线/悬念线)。 */
331
- export interface Plotline {
332
- /** 稳定 id。 */
333
- id: string
334
- /** 线名。 */
335
- name: string
336
- /** 类型:主线 / 支线 / 人物线 / 悬念线。 */
337
- kind: 'main' | 'branch' | 'character' | 'mystery'
338
- /** 目标/终点(这条线最终要完成什么)。 */
339
- goal: string
340
- /** 当前进度说明(最近推进到哪)。 */
341
- progress: string
342
- /** 生命周期状态。 */
343
- status: 'active' | 'paused' | 'resolved' | 'abandoned'
344
- /** 关联章节号(推进/落地的章节)。 */
345
- chapters: number[]
346
- /** 创建时间。 */
347
- createdAt: string
348
- }
349
-
350
- /** POST /plotlines 请求:剧情线增删改 + 关联章节 + AI 辅助。 */
351
- export interface PlotlinesRequest {
352
- op: 'add' | 'update' | 'remove' | 'link' | 'suggest' | 'refresh' | 'health' | 'plan'
353
- /** add / update 时传入的完整剧情线。 */
354
- line?: Plotline
355
- /** remove / link / refresh 时的目标线 id。 */
356
- id?: string
357
- /** link 时关联的章节号。 */
358
- chapterNo?: number
359
- }
360
-
361
- /** 剧情线健康检查报告。 */
362
- export interface PlotlineHealthReport {
363
- /** 是否需要新线(需要 / 暂不需要 / 再写 X 章后需要)。 */
364
- verdict: string
365
- /** 建议添加新线的时机说明。 */
366
- timing: string
367
- /** 依据(基于数据的理由,每条一句)。 */
368
- reasons: string[]
369
- /** 各线健康度。 */
370
- lines: Array<{
371
- name: string
372
- /** ok=健康 / warning=预警 / stale=搁置过久。 */
373
- health: 'ok' | 'warning' | 'stale'
374
- note: string
375
- }>
376
- }
377
-
378
- /** AI 剧情方案:下一阶段目标 + 建议新线。 */
379
- export interface PlotlinePlan {
380
- /** 下一阶段(未来 5-10 章)剧情方向。 */
381
- direction: string
382
- /** 建议的新线(可逐条采纳)。 */
383
- suggestions: Plotline[]
384
- }
385
-
386
- /** POST /plotlines 响应。 */
387
- export interface PlotlinesResponse {
388
- plotlines: Plotline[]
389
- /** op=suggest 时的 AI 建议候选线。 */
390
- suggestions?: Plotline[]
391
- /** op=health 时的健康检查报告。 */
392
- health?: PlotlineHealthReport
393
- /** op=plan 时的剧情方案。 */
394
- plan?: PlotlinePlan
395
- }
396
-
397
- /** 一条敏感词命中。 */
398
- export interface SensitiveHit {
399
- /** 命中章节号(文本检测时为 0)。 */
400
- chapterNo: number
401
- /** 命中的违禁词。 */
402
- word: string
403
- /** 类别:政治 / 擦边 / 暴力 / 辱骂 / 广告 / 其他。 */
404
- category: string
405
- /** 出现次数。 */
406
- count: number
407
- }
408
-
409
- /** POST /sensitive-check 请求:检测指定章节/任意文本/全书。 */
410
- export interface SensitiveCheckRequest {
411
- /** 检测该章正文。 */
412
- chapterNo?: number
413
- /** 检测任意文本(优先于 chapterNo)。 */
414
- text?: string
415
- /** 扫描全部已写章节。 */
416
- all?: boolean
417
- }
418
-
419
- /** POST /sensitive-check 响应。 */
420
- export interface SensitiveCheckResponse {
421
- hits: SensitiveHit[]
422
- /** 参与扫描的章节数。 */
423
- scannedChapters: number
424
- }
425
-
426
- /** 开书想法 → AI 大纲方案(一个候选)。 */
427
- export interface OutlineCandidate {
428
- /** 唯一 id(前端暂留/换批用)。 */
429
- id: string
430
- /** 推荐书名。 */
431
- bookName: string
432
- /** 题材(如 仙侠修真 / 都市)。 */
433
- genre: string
434
- /** 核心卖点一句话。 */
435
- sellingPoint: string
436
- /** 完整大纲文本(可直接用作项目大纲,≥800 字)。 */
437
- outline: string
438
- }
439
-
440
- /** POST /outline/suggest 请求:想法 → 2-3 个可选大纲。 */
441
- export interface OutlineSuggestRequest {
442
- /** 作者想法(一两句话,≥50 字)。 */
443
- idea: string
444
- /** 本次要生成的候选数(默认 3,最多 3)。 */
445
- count?: number
446
- /** 已暂留方案的剧情方向摘要(换批时让 LLM 避开,防止与已留方案重复)。 */
447
- exclude?: string[]
448
- }
449
-
450
- /** POST /outline/suggest 响应。 */
451
- export interface OutlineSuggestResponse {
452
- candidates: OutlineCandidate[]
453
- }
454
-
455
- /** 拆书分析:一个分析小节。 */
456
- export interface BreakdownSection {
457
- /** 小节键:overview / plot / character / style / market。 */
458
- key: string
459
- /** 小节标题(如「拆书总览」)。 */
460
- title: string
461
- /** 可读分析稿(markdown)。 */
462
- markdown: string
463
- /** 结构化数据(程序可消费)。 */
464
- structured: Record<string, unknown>
465
- }
466
-
467
- /** 拆书分析:一条证据(结论→原文回溯)。 */
468
- export interface BreakdownEvidence {
469
- label: string
470
- excerpt: string
471
- /** 来源章节号(0 = 未定位)。 */
472
- chapterNo: number
473
- /** 指向的结构化字段。 */
474
- fieldKey?: string
475
- }
476
-
477
- /** POST /breakdown 请求:对已写章节做拆书分析。 */
478
- export interface BreakdownRequest {
479
- /** 分析范围:'recent'=最近 20 章 / 'volume:N'=第 N 卷 / 'all'=全书(默认 recent)。 */
480
- scope?: string
481
- /** 分析档位:'quick'=4 维(总览/剧情/人物/文风)/ 'standard'=5 维(+卖点)。 */
482
- preset?: 'quick' | 'standard'
483
- /** token 预算上限(默认 50000)。 */
484
- budgetTokens?: number
485
- }
486
-
487
- /** POST /breakdown 响应。 */
488
- export interface BreakdownResponse {
489
- sections: BreakdownSection[]
490
- evidence: BreakdownEvidence[]
491
- /** 参与分析的章节数。 */
492
- chaptersScanned: number
493
- /** 估算消耗 token。 */
494
- usedTokens: number
495
- }
496
-
497
- /** 漫剧分镜:一个角色锚点卡。 */
498
- export interface StoryboardCharacterCard {
499
- name: string
500
- /** 视觉锚点:发型/五官/体型/标志物(中文描述)。 */
501
- visualAnchor: string
502
- /** AI 标签组(英文,全分镜强制复用)。 */
503
- tags: string
504
- /** 情绪表情库(英文,按需调用)。 */
505
- expressions: string[]
506
- }
507
-
508
- /** 漫剧分镜:一个分镜格。 */
509
- export interface StoryboardPanel {
510
- /** 序号。 */
511
- index: number
512
- /** 时间码(如 0:00-0:03)。 */
513
- timecode: string
514
- /** 景别(特写/中景/全景…)。 */
515
- shot: string
516
- /** 画面描述(具象动作,非抽象情感)。 */
517
- visual: string
518
- /** 台词(情绪标签 + 内容)。 */
519
- dialogue: string
520
- /** 转场/动效。 */
521
- transition: string
522
- /** AI 提示词(英文标签,豆包/SD 通用)。 */
523
- prompt: string
524
- }
525
-
526
- /** POST /storyboard 请求:章节 → 漫剧分镜。 */
527
- export interface StoryboardRequest {
528
- chapterNo: number
529
- /** 赛道类型:爽文/甜宠/悬疑/搞笑(留空由 AI 推断)。 */
530
- genre?: string
531
- /** 目标平台(抖音/快手/B站…,默认抖音)。 */
532
- platform?: string
533
- /** AI 工具偏好:doubao / seedance / sd / mj(影响提示词格式,默认 doubao)。 */
534
- tool?: string
535
- }
536
-
537
- /** POST /storyboard 响应。 */
538
- export interface StoryboardResponse {
539
- /** 本集标题。 */
540
- title: string
541
- /** 赛道与节奏说明。 */
542
- pacingNote: string
543
- /** 本集钩子(结尾悬念)。 */
544
- hook: string
545
- /** 角色锚点卡。 */
546
- characters: StoryboardCharacterCard[]
547
- /** 分镜表。 */
548
- panels: StoryboardPanel[]
549
- /** 结尾钩子台词。 */
550
- endingHook: string
551
- }
552
-
553
- /** 漫剧分集计划:一集(含 1-N 章)。 */
554
- export interface StoryboardEpisode {
555
- /** 集号。 */
556
- index: number
557
- /** 集标题(冲突+悬念句式)。 */
558
- title: string
559
- /** 涵盖章节号。 */
560
- chapters: number[]
561
- /** 叙事任务:这集讲什么、为什么这么分。 */
562
- narrativeJob: string
563
- /** 开头钩子。 */
564
- openingHook: string
565
- /** 结尾钩子(逼看下集)。 */
566
- endingHook: string
567
- }
568
-
569
- /** POST /storyboard/plan 请求:读一卷 → 输出漫剧分集计划。 */
570
- export interface StoryboardPlanRequest {
571
- /** 卷号(1-5)。 */
572
- volumeNo: number
573
- /** 目标平台(默认抖音)。 */
574
- platform?: string
575
- /** 每集约 1-2 分钟,最多多少集(默认 25)。 */
576
- maxEpisodes?: number
577
- }
578
-
579
- /** POST /storyboard/plan 响应。 */
580
- export interface StoryboardPlanResponse {
581
- /** 本卷漫剧化的叙事策略说明。 */
582
- strategy: string
583
- /** 分集计划。 */
584
- episodes: StoryboardEpisode[]
585
- /** 参与规划的章节数。 */
586
- chaptersScanned: number
587
- }
588
-
589
- /** 角色卡:角色当前状态(从事实库聚合)。 */
590
- export interface RoleStatusCard {
591
- name: string
592
- /** protagonist / supporting / antagonist / other。 */
593
- role: string
594
- /** 当前状态一句话(境界/资源/伤势/心境)。 */
595
- status: string
596
- /** 最近出场章节。 */
597
- lastChapter: number
598
- /** 出场次数。 */
599
- appearances: number
600
- }
601
-
602
- /** 角色库条目(主表:作者维护 + AI 提炼 + 编年录自动聚合)。 */
603
- export interface RoleRecord {
604
- /** 角色名(唯一键)。 */
605
- name: string
606
- /** 定位:主角 / 女主 / 女配 / 配角 / 反派 / 路人。 */
607
- roleLabel: 'protagonist' | 'female_lead' | 'female_support' | 'support' | 'antagonist' | 'extra'
608
- /** 身份一句话(如:祭族后裔、青云宗杂役)。 */
609
- identity: string
610
- /** 性格标签。 */
611
- traits: string[]
612
- /** 目标与动机。 */
613
- goals: string
614
- /** 关系网:[角色名](关系)。 */
615
- relations: string[]
616
- /** 成长线:阶段 → 说明(可含章节)。 */
617
- arc: string[]
618
- /** 知情度:该角色已经知道的信息。 */
619
- knowledge: string[]
620
- /** 首次出场章节(编年录聚合,可手动修正)。 */
621
- firstChapter?: number
622
- /** 动漫形象描述词(AI 绘图用:中文描述 + 英文标签 + 关键外貌标签)。 */
623
- imagePrompt?: {
624
- /** 中文外貌描述:连贯一段(发色/瞳色/服装/气质/标志物)。 */
625
- zh: string
626
- /** 英文绘图标签:booru 风格逗号分隔。 */
627
- en: string
628
- /** 中文关键标签(发色/瞳色/服装/气质/标志物)。 */
629
- tags: string[]
630
- /** 依据来源说明(哪几章哪些描写)。 */
631
- source?: string
632
- }
633
- }
634
-
635
- /** POST /roles 请求:角色库增删改 + AI 提炼。 */
636
- export interface RolesRequest {
637
- op: 'extract' | 'adopt' | 'update' | 'remove' | 'visual'
638
- /** adopt / update 时传入的角色(adopt 可修改后采纳)。 */
639
- role?: RoleRecord
640
- /** remove 时的角色名。 */
641
- name?: string
642
- }
643
-
644
- /** POST /roles 响应。 */
645
- export interface RolesResponse {
646
- roles: RoleRecord[]
647
- /** op=extract 时的 AI 候选角色。 */
648
- candidates?: RoleRecord[]
649
- /** op=visual 时的动漫形象描述词(已写入角色卡)。 */
650
- visual?: RoleRecord['imagePrompt']
651
- }
652
-
653
- /** POST /bible/patch 请求:局部修补设定圣经。 */
654
- export interface BiblePatchRequest {
655
- worldRules?: string[]
656
- redLines?: string[]
657
- style?: string[]
658
- /** 角色卡整体替换(人物志编辑知情度等)。 */
659
- characters?: CharacterCard[]
660
- }
661
-
662
- /** POST /blurb 请求:AI 生成/补全或手动保存小说简介。 */
663
- export interface BlurbRequest {
664
- action: 'generate' | 'save'
665
- /** 已写好的开头(AI 补全时使用;留空 = 全量生成)。 */
666
- partial?: string
667
- /** 手动保存的完整简介(action=save 时)。 */
668
- text?: string
669
- }
670
-
671
- /** POST /chapter/check|save 请求:审查/保存手动编辑的正文。 */
672
- export interface ChapterTextRequest {
673
- chapterNo: number
674
- /** 当前编辑中的正文全文。 */
675
- text: string
676
- /** 保存时携带:已在工作区审查过的报告(沿用落盘,不重复审);缺省则保存后自动正式审稿一次。 */
677
- report?: ReviewReport
678
- /** 审查/验证时携带:上一轮审稿报告。传入后进入「验证模式」——逐条核对原意见是否解决、
679
- * 只挑新增 high,不再全新找茬(防止"越修 high 越多")。 */
680
- previousReport?: ReviewReport
681
- }
682
-
683
- /** POST /chapter/save 响应。 */
684
- export interface ChapterSaveResponse {
685
- ok: boolean
686
- chars: number
687
- file: string
688
- /** 落盘的审稿报告(沿用工作区报告或保存后自动审稿)。 */
689
- report?: ReviewReport
690
- }
691
-
692
- /** POST /cover 请求:上传或移除封面。 */
693
- export interface CoverRequest {
694
- action: 'upload' | 'remove'
695
- /** 上传时:data:image/...;base64,... 格式的图片数据。 */
696
- dataUrl?: string
697
- }
698
-
699
- /** POST /rename 请求:重命名当前书。 */
700
- export interface RenameRequest {
701
- bookName: string
702
- }
703
-
704
- /** 大世界:一个境界等级。 */
705
- export interface WorldRealm {
706
- /** 境界名(练气/筑基/金丹…)。 */
707
- name: string
708
- /** 描述:突破条件/寿命/标志等。 */
709
- description: string
710
- }
711
-
712
- /** 大世界:一个地理区域。 */
713
- export interface WorldRegion {
714
- name: string
715
- description: string
716
- /** 关联势力名(可空)。 */
717
- faction?: string
718
- }
719
-
720
- /** 大世界:一方势力。 */
721
- export interface WorldFaction {
722
- name: string
723
- /** 类型:宗门/家族/王朝/组织… */
724
- kind: string
725
- description: string
726
- /** 驻地区域(可空)。 */
727
- region?: string
728
- }
729
-
730
- /** 大世界结构化数据。 */
731
- export interface WorldState {
732
- realms: WorldRealm[]
733
- regions: WorldRegion[]
734
- factions: WorldFaction[]
735
- }
736
-
737
- /** POST /world 请求:AI 提炼或手动保存。 */
738
- export interface WorldRequest {
739
- action: 'generate' | 'save'
740
- /** action=save 时的完整世界数据。 */
741
- world?: WorldState
742
- }
743
-
744
- /** GET /cover 响应:封面的 dataUrl(无封面为 null)。 */
745
- export interface CoverResponse {
746
- dataUrl: string | null
747
- }
748
-
749
- /** The persisted project: outline + bible + plan + progress. */
750
- export interface ProjectState {
751
- /** Book title (first non-empty line of the outline, usually). */
752
- bookName: string
753
- /** Full outline text (docx-extracted or pasted). */
754
- outline: string
755
- /** Source outline path when loaded from a docx. */
756
- outlinePath?: string
757
- /** Structured story bible (worldbuilding), if generated. */
758
- bible?: StoryBible
759
- /** Volumes, if planned. */
760
- volumes?: Volume[]
761
- /** Chapter plan. */
762
- chapters: ChapterPlan[]
763
- /** Foreshadowing threads. */
764
- foreshadows: Foreshadow[]
765
- /** 写作资产(题材基底/推进模式/反AI规则/写法资产)。 */
766
- assets?: ProjectAssets
767
- /** 事实库/时间线:每章生成后抽取,注入后续章节保持一致性。 */
768
- facts?: ChapterFact[]
769
- /** 小说简介(面向读者的作品门面,AI 生成或手动保存)。 */
770
- blurb?: string
771
- /** 封面文件名(相对输出目录,如 cover.png)。 */
772
- coverPath?: string
773
- /** 大世界结构化数据(境界体系/区域/势力)。 */
774
- world?: WorldState
775
- /** 剧情线(主线/支线/人物线/悬念线)。 */
776
- plotlines?: Plotline[]
777
- /** 角色库(作者维护 + AI 提炼的主表)。 */
778
- roles?: RoleRecord[]
779
- /** 人物志:角色当前状态聚合结果(从编年录刷新后存档,打开页面直接显示)。 */
780
- roleStatus?: RoleStatusCard[]
781
- /** ISO timestamps. */
782
- createdAt: string
783
- updatedAt: string
784
- }
785
-
786
- /** Runtime config surface exposed to the panel (subset of plugin Config). */
787
- export interface NovelConfig {
788
- /** Absolute path of the default docx outline to load. */
789
- outlinePath: string
790
- /** Absolute output directory for chapters + project state. */
791
- outputDir: string
792
- /** LLM provider route (e.g. deepseek-official). */
793
- provider: string
794
- /** LLM model id (e.g. deepseek-v4-flash). */
795
- model: string
796
- /** LLM reasoning effort: off = no thinking; low/high/max = thinking intensity. */
797
- reasoningEffort: 'off' | 'low' | 'high' | 'max'
798
- /** Target characters per chapter. */
799
- chapterChars: number
800
- /** Max output tokens per chapter call. */
801
- maxTokens: number
802
- /** Review pass threshold (0-100). */
803
- reviewPassScore: number
804
- /** Whether generation auto-runs review after writing. */
805
- autoReview: boolean
806
- /** Whether generation auto-runs the author review (hook/continuity/trend) after writing. */
807
- autoAuthorReview: boolean
808
- /** 修订/润色产出草稿后是否自动附带一次 AI 审查(工作区显示新稿评分与剩余问题)。 */
809
- autoReviewAfterRevise: boolean
810
- }
811
-
812
- /** GET /status response. */
813
- export interface StatusResponse {
814
- config: NovelConfig
815
- /** The persisted project, when one exists in the output dir. */
816
- project?: ProjectState
817
- /** Chapter files already on disk (basenames, sorted). */
818
- generatedFiles: string[]
819
- /** 全书质检实时状态(用于面板/外部读取进度)。 */
820
- audit?: AuditStatus
821
- }
822
-
823
- /** 生产单状态(生产单 = 区间批量生产执行器:计划补足 + 逐章生成 + 被拒分级处理)。 */
824
- export interface RunState {
825
- runId: string
826
- /** 区间起点(含)。 */
827
- startNo: number
828
- /** 区间终点(含)。 */
829
- endNo: number
830
- status: 'running' | 'paused' | 'done' | 'stopped' | 'error'
831
- /** 当前处理到的章号(已 approved 的章会快进)。 */
832
- currentNo: number
833
- stats: {
834
- /** 新生成(含审稿)的章数。 */
835
- generated: number
836
- /** 被拒后按意见修订并通过的章数。 */
837
- revised: number
838
- /** 被拒后豁免通过(无 high)的章数。 */
839
- exempted: number
840
- /** error 后重新生成的章数。 */
841
- regenerated: number
842
- /** 生成失败的章数。 */
843
- error: number
844
- }
845
- /** 两轮修订仍不过、保留草稿待人工的章号。 */
846
- pendingManual: number[]
847
- /** 运行日志(保留最近 300 条)。 */
848
- log: Array<{ at: string; text: string }>
849
- startedAt: string
850
- updatedAt: string
851
- error?: string
852
- }
853
-
854
- /** POST /run/start request. */
855
- export interface RunStartRequest {
856
- /** 起始章号(默认 1)。 */
857
- startNo?: number
858
- /** 结束章号(含;超出计划时自动补计划)。 */
859
- endNo?: number
860
- /** 或指定新增章数(从当前最后一章 +1 起)。 */
861
- count?: number
862
- }
863
-
864
- /** POST /run/control request. */
865
- export interface RunControlRequest {
866
- action: 'pause' | 'resume' | 'stop'
867
- }
868
-
869
- /** POST /load-outline request: either a docx path or raw text. */
870
- export interface LoadOutlineRequest {
871
- /** Absolute docx path; defaults to the configured outline path. */
872
- path?: string
873
- /** Raw outline text (takes precedence over path when present). */
874
- text?: string
875
- }
876
-
877
- /** POST /load-outline response. */
878
- export interface LoadOutlineResponse {
879
- outline: string
880
- bookName: string
881
- chars: number
882
- path?: string
883
- }
884
-
885
- /** POST /plan request. */
886
- export interface PlanRequest {
887
- /** Outline to plan from; defaults to the persisted project's outline. */
888
- outline?: string
889
- /** Number of chapters to plan (default: 30). */
890
- chapterCount?: number
891
- /** Volume to plan (1-based); when given, plans only that volume's chapters. */
892
- volume?: number
893
- }
894
-
895
- /** POST /plan response. */
896
- export interface PlanResponse {
897
- chapters: ChapterPlan[]
898
- volumes?: Volume[]
899
- }
900
-
901
- /** POST /volumes request/response. */
902
- export interface VolumesRequest {
903
- /** Outline to split into volumes; defaults to the project outline. */
904
- outline?: string
905
- }
906
- export interface VolumesResponse {
907
- volumes: Volume[]
908
- }
909
-
910
- /** POST /bible request/response. */
911
- export interface BibleRequest {
912
- /** Outline to extract from; defaults to the project outline. */
913
- outline?: string
914
- }
915
- export interface BibleResponse {
916
- bible: StoryBible
917
- }
918
-
919
- /** POST /generate request: one chapter of the current project. */
920
- export interface GenerateRequest {
921
- chapterNo: number
922
- /** When true, skips the auto-review step. */
923
- skipReview?: boolean
924
- }
925
-
926
- /** One NDJSON frame of a generation/review/rewrite stream. */
927
- export type JobFrame =
928
- | { type: 'start'; no: number; title: string }
929
- | { type: 'delta'; text: string }
930
- | { type: 'progress'; chars: number }
931
- | { type: 'done'; no: number; file: string; chars: number; title: string }
932
- | { type: 'review'; no: number; report: ReviewReport }
933
- | { type: 'author-review'; no: number; review: AuthorReview }
934
- | { type: 'author-backfill-done'; count: number }
935
- | { type: 'rewritten'; no: number; file: string; chars: number }
936
- /** 润色/重写完成,产物作为待确认草稿(尚未覆盖正文)。 */
937
- | { type: 'drafted'; no: number; chars: number; draft: string }
938
- | { type: 'error'; no: number; message: string }
939
-
940
- /** POST /review request: review one written chapter. */
941
- export interface ReviewRequest {
942
- chapterNo: number
943
- }
944
-
945
- /** POST /rewrite request: rewrite one chapter (optionally per review issues). */
946
- export interface RewriteRequest {
947
- chapterNo: number
948
- /** Free-form instructions; defaults to fixing the review's high issues. */
949
- instructions?: string
950
- /**
951
- * 局部修订:正文中的一段原文(无需完全精确,取一个自然段内的片段即可)。
952
- * 提供时只重写该段,其余正文保持不变;不提供时整章重写。
953
- */
954
- target?: string
955
- }
956
-
957
- /** POST /polish request: de-AI-ify one chapter. */
958
- export interface PolishRequest {
959
- chapterNo: number
960
- }
961
-
962
- /** POST /draft/apply | /draft/discard request: 采纳或放弃待确认草稿。 */
963
- export interface DraftDecisionRequest {
964
- chapterNo: number
965
- /** apply 时可携带审查报告(沿用结论定状态;不携带则置 written)。 */
966
- report?: ReviewReport
967
- }
968
-
969
- /** POST /summary request: (re)generate a chapter summary. */
970
- export interface SummaryRequest {
971
- chapterNo: number
972
- }
973
-
974
- /** POST /foreshadow request: create, update, or AI-suggest foreshadows. */
975
- export interface ForeshadowRequest {
976
- /** When true, runs the LLM suggestion pass (ignores other fields). */
977
- suggest?: boolean
978
- /** When given, updates that foreshadow instead of creating one. */
979
- id?: string
980
- description?: string
981
- plantedChapter?: number
982
- targetChapter?: number
983
- status?: Foreshadow['status']
984
- resolvedNote?: string
985
- }
986
- export interface ForeshadowResponse {
987
- foreshadows: Foreshadow[]
988
- }
989
-
990
- /** GET /chapter response. */
991
- export interface ChapterResponse {
992
- no: number
993
- title: string
994
- markdown: string
995
- }
996
-
997
- /** POST /export request/response. */
998
- export interface ExportRequest {
999
- format: 'txt' | 'md'
1000
- }
1001
- export interface ExportResponse {
1002
- file: string
1003
- chars: number
1004
- chapters: number
1005
- }
1006
-
1007
- /** POST /config request: patch any subset of the runtime config. */
1008
- export interface ConfigPatch {
1009
- outlinePath?: string
1010
- outputDir?: string
1011
- provider?: string
1012
- model?: string
1013
- reasoningEffort?: 'off' | 'low' | 'high' | 'max'
1014
- chapterChars?: number
1015
- maxTokens?: number
1016
- reviewPassScore?: number
1017
- autoReview?: boolean
1018
- autoAuthorReview?: boolean
1019
- autoReviewAfterRevise?: boolean
1020
- }
1021
-
1022
- // ------------------------------------------------------------ assistant
1023
-
1024
- /** One assistant conversation message (persisted per project). */
1025
- export interface AssistantMessage {
1026
- role: 'user' | 'assistant' | 'tool'
1027
- /** Message text (tool messages carry the tool result). */
1028
- content: string
1029
- /** ISO timestamp. */
1030
- ts: string
1031
- /** For tool messages: which tool ran. */
1032
- tool?: string
1033
- }
1034
-
1035
- /** POST /assistant request: one user turn. */
1036
- export interface AssistantRequest {
1037
- message: string
1038
- }
1039
-
1040
- /** One NDJSON frame of the assistant stream. */
1041
- export type AssistantFrame =
1042
- | { type: 'delta'; text: string }
1043
- | { type: 'tool'; name: string; status: 'start' | 'done' | 'error'; detail?: string }
1044
- /** Live output while a tool runs (e.g. chapter text being generated). */
1045
- | { type: 'toolDelta'; name: string; text: string }
1046
- | { type: 'done' }
1047
- | { type: 'error'; message: string }
1048
-
1049
- /** GET /assistant-history response. */
1050
- export interface AssistantHistoryResponse {
1051
- messages: AssistantMessage[]
1052
- }
1053
-
1054
- // ---------------------------------------------------------- writing assets
1055
-
1056
- /** 题材基底库:一本书属于哪个阅读市场。树形(题材→子题材→下级)。 */
1057
- export interface GenreNode {
1058
- /** 题材名称(标签,如「仙侠修真」「都市异能」)。 */
1059
- name: string
1060
- /** 题材特征、常见爽点、叙事重心或读者期待。 */
1061
- description: string
1062
- /** 子题材。 */
1063
- children: GenreNode[]
1064
- }
1065
-
1066
- /** 推进模式库:读者为什么继续看下一章。 */
1067
- export interface ProgressionMode {
1068
- /** 模式名称(如「升级变强」「经营扩张」「解谜揭露」)。 */
1069
- name: string
1070
- /** 核心驱动力:靠什么制造追读动力。 */
1071
- driver: string
1072
- /** 读者期待:每隔几章获得什么变化或回报。 */
1073
- readerExpectation: string
1074
- /** 常见兑现方式(爽点如何落地)。 */
1075
- payoffs: string[]
1076
- /** 节奏风险:最怕什么(重复升级、冲突变弱、谜题拖太久…)。 */
1077
- risks: string[]
1078
- /** 主模式或辅助模式。 */
1079
- primary: boolean
1080
- }
1081
-
1082
- /** 反 AI 规则:一条「要避免的问题 + 修正方向」。 */
1083
- export interface AntiAiRule {
1084
- /** 规则名(如「禁止解释型心理描写」「AI 高频套话」)。 */
1085
- name: string
1086
- /** 要避免的表达问题,具体可检查。 */
1087
- avoid: string
1088
- /** 推荐修正方向。 */
1089
- fix: string
1090
- /** 命中即告警的具体表达模式(用于审稿逐条核对与去 AI 味检测)。 */
1091
- detectPatterns?: string[]
1092
- /** 是否内置全局规则(内置规则随插件发布,项目规则为用户自定义)。 */
1093
- builtin?: boolean
1094
- }
1095
-
1096
- /** 预置写法模板(来自 AI-Novel-Writing-Assistant 内置数据,一键绑定无需样本文本)。 */
1097
- export interface StyleTemplate {
1098
- /** 模板 key(如 power-up-escalation)。 */
1099
- key: string
1100
- /** 模板名(如「爽文递进推进流」)。 */
1101
- name: string
1102
- /** 模板说明。 */
1103
- description: string
1104
- /** 分类(如「爽文流」「悬疑流」)。 */
1105
- category: string
1106
- /** 适用题材。 */
1107
- applicableGenres: string[]
1108
- /** 叙述规则。 */
1109
- proseRules: string[]
1110
- /** 角色/台词规则。 */
1111
- dialogueRules: string[]
1112
- /** 语言规则。 */
1113
- languageRules: string[]
1114
- /** 节奏规则。 */
1115
- rhythmRules: string[]
1116
- /** 该模板默认绑定的反 AI 规则 key(内置规则名)。 */
1117
- defaultAntiAiRuleKeys: string[]
1118
- }
1119
-
1120
- /** 写法引擎:从样本文本提取的叙事风格资产。 */
1121
- export interface StyleAsset {
1122
- /** 资产名(如「林越式痞坏」「冷峻猎手风」)。 */
1123
- name: string
1124
- /** 叙述视角与句式节奏。 */
1125
- proseRules: string[]
1126
- /** 角色台词风格。 */
1127
- dialogueRules: string[]
1128
- /** 描写密度与情绪表达。 */
1129
- descriptionRules: string[]
1130
- /** 表达边界(不要做什么)。 */
1131
- boundaries: string[]
1132
- /** 来源样本文本(可空)。 */
1133
- sourceText?: string
1134
- /** 创建时间。 */
1135
- createdAt: string
1136
- }
1137
-
1138
- /** 项目写作资产(题材基底 + 推进模式 + 反 AI 规则 + 写法资产)。 */
1139
- export interface ProjectAssets {
1140
- /** 本书选用的题材(可以是题材基底库中某节点名)。 */
1141
- genre?: GenreNode
1142
- /** 主推进模式。 */
1143
- primaryProgression?: ProgressionMode
1144
- /** 辅助推进模式。 */
1145
- auxiliaryProgressions: ProgressionMode[]
1146
- /** 生效的反 AI 规则(内置 + 自定义)。 */
1147
- antiAiRules: AntiAiRule[]
1148
- /** 绑定的写法资产。 */
1149
- styleAssets: StyleAsset[]
1150
- /** 资产更新时间。 */
1151
- updatedAt?: string
1152
- }
1153
-
1154
- /** GET /assets response(含全局题材库与反 AI 规则库)。 */
1155
- export interface AssetsResponse {
1156
- projectAssets: ProjectAssets
1157
- /** 全局题材基底库(可复用资产,跨书)。 */
1158
- genreLibrary: GenreNode[]
1159
- /** 全局反 AI 规则库(内置默认规则)。 */
1160
- antiAiLibrary: AntiAiRule[]
1161
- /** 预置写法模板(一键绑定,无需样本文本)。 */
1162
- styleTemplates: StyleTemplate[]
1163
- /** 内置推进模式候选。 */
1164
- progressionLibrary: ProgressionMode[]
1165
- }
1166
-
1167
- /** POST /assets request:更新项目写作资产(部分字段可选)。 */
1168
- export interface AssetsPatch {
1169
- genre?: GenreNode
1170
- primaryProgression?: ProgressionMode
1171
- auxiliaryProgressions?: ProgressionMode[]
1172
- antiAiRules?: AntiAiRule[]
1173
- styleAssets?: StyleAsset[]
1174
- }
1175
-
1176
- /** POST /style-engine request:从样本文本提取写法资产。 */
1177
- export interface StyleEngineRequest {
1178
- /** 样本文本(风格来源)。 */
1179
- sampleText: string
1180
- /** 资产名(可选,默认「风格资产 N」)。 */
1181
- name?: string
1182
- }
1
+ /**
2
+ * dsh-novel-forge — shared protocol between the host half (Node) and the
3
+ * browser half (web GUI). Route paths, request/response shapes, the project
4
+ * state file format, and the NDJSON generation stream frames all live here so
5
+ * both halves spell exactly one vocabulary.
6
+ */
7
+
8
+ /** The /api/dsh-novel-forge route family (same-origin, loopback-fenced). */
9
+ export const NOVEL_API = {
10
+ status: '/api/dsh-novel-forge/status',
11
+ loadOutline: '/api/dsh-novel-forge/load-outline',
12
+ saveOutline: '/api/dsh-novel-forge/save-outline',
13
+ plan: '/api/dsh-novel-forge/plan',
14
+ volumes: '/api/dsh-novel-forge/volumes',
15
+ bible: '/api/dsh-novel-forge/bible',
16
+ assets: '/api/dsh-novel-forge/assets',
17
+ styleEngine: '/api/dsh-novel-forge/style-engine',
18
+ styleFormula: '/api/dsh-novel-forge/style-formula',
19
+ styleDetect: '/api/dsh-novel-forge/style-detect',
20
+ knowledge: '/api/dsh-novel-forge/knowledge',
21
+ bookAnalysis: '/api/dsh-novel-forge/book-analysis',
22
+ ideaInspiration: '/api/dsh-novel-forge/idea-inspiration',
23
+ ideaInspirationMarket: '/api/dsh-novel-forge/idea-inspiration/market',
24
+ director: '/api/dsh-novel-forge/director',
25
+ directorTodos: '/api/dsh-novel-forge/director/todos',
26
+ llmLive: '/api/dsh-novel-forge/llm-live/stream',
27
+ marketRadar: '/api/dsh-novel-forge/market-radar',
28
+ marketRadarScan: '/api/dsh-novel-forge/market-radar/scan',
29
+ marketRadarApply: '/api/dsh-novel-forge/market-radar/apply',
30
+ marketRadarSync: '/api/dsh-novel-forge/market-radar/foundation-sync',
31
+ marketRadarBrief: '/api/dsh-novel-forge/market-radar/brief',
32
+ generate: '/api/dsh-novel-forge/generate',
33
+ review: '/api/dsh-novel-forge/review',
34
+ rewrite: '/api/dsh-novel-forge/rewrite',
35
+ polish: '/api/dsh-novel-forge/polish',
36
+ /** 采纳待确认草稿(润色/重写产物)覆盖正文文件。 */
37
+ draftApply: '/api/dsh-novel-forge/draft/apply',
38
+ /** 放弃待确认草稿,保留原稿。 */
39
+ draftDiscard: '/api/dsh-novel-forge/draft/discard',
40
+ summary: '/api/dsh-novel-forge/summary',
41
+ foreshadow: '/api/dsh-novel-forge/foreshadow',
42
+ exportBook: '/api/dsh-novel-forge/export',
43
+ chapter: '/api/dsh-novel-forge/chapter',
44
+ /** 审查任意正文文本(作者手动编辑后,不落盘)。 */
45
+ chapterCheck: '/api/dsh-novel-forge/chapter/check',
46
+ /** 保存手动编辑的正文(自动备份 .bak)。 */
47
+ chapterSave: '/api/dsh-novel-forge/chapter/save',
48
+ assistant: '/api/dsh-novel-forge/assistant',
49
+ assistantHistory: '/api/dsh-novel-forge/assistant-history',
50
+ /** 清空助手对话记录。 */
51
+ assistantClear: '/api/dsh-novel-forge/assistant/clear',
52
+ bookshelf: '/api/dsh-novel-forge/bookshelf',
53
+ /** 导入已有项目目录(含 novel-project.json)到书架。 */
54
+ bookshelfImportDir: '/api/dsh-novel-forge/bookshelf/import-dir',
55
+ /** 导入 txt/md 全本:拆章建项目并登记书架。 */
56
+ bookshelfImportText: '/api/dsh-novel-forge/bookshelf/import-text',
57
+ /** 导入 txt/md 全本:拆章预览(不落盘)。 */
58
+ bookshelfImportTextPreview: '/api/dsh-novel-forge/bookshelf/import-text/preview',
59
+ /** LLM 模型连通性测试:真实最小调用,验证 Key / 端点 / 模型可用。 */
60
+ llmTest: '/api/dsh-novel-forge/llm-test',
61
+ /** 添加模型:厂商直填 key 或自定义路由,写进 DSH 凭据与 llm-pi-ai 路由。 */
62
+ addModel: '/api/dsh-novel-forge/llm-add',
63
+ /** 运行时厂商目录(DSH pi-ai 可配置提供方 + 内置适配器)。 */
64
+ llmVendors: '/api/dsh-novel-forge/llm-vendors',
65
+ /** 查询某个 provider 当前可用的模型(添加成功后可即时刷新)。 */
66
+ llmModels: '/api/dsh-novel-forge/llm-models',
67
+ /** 已注册的提供方路由列表(提供方管理)。 */
68
+ llmProviders: '/api/dsh-novel-forge/llm-providers',
69
+ /** 移除一个提供方。 */
70
+ llmRemove: '/api/dsh-novel-forge/llm-remove',
71
+ /** 重置项目(可选携带新大纲):清空设定/卷/章节/伏笔/资产/事实库。 */
72
+ reset: '/api/dsh-novel-forge/reset',
73
+ /** 全书一致性质检:LLM 扫描已生成章节,输出矛盾问题清单。 */
74
+ audit: '/api/dsh-novel-forge/audit',
75
+ /** 角色卡刷新:基于事实库与各章摘要聚合角色当前状态。 */
76
+ charactersRefresh: '/api/dsh-novel-forge/characters/refresh',
77
+ /** 事实库回填:对历史已生成章节批量抽取事实(旧章节无事实记录时用)。 */
78
+ factsBackfill: '/api/dsh-novel-forge/facts/backfill',
79
+ /** 道藏局部修补(如世界观规则编辑)。 */
80
+ biblePatch: '/api/dsh-novel-forge/bible/patch',
81
+ /** 小说简介:生成(AI)/补全(AI)/保存。 */
82
+ blurb: '/api/dsh-novel-forge/blurb',
83
+ /** 重命名当前书(同步项目与书架条目)。 */
84
+ rename: '/api/dsh-novel-forge/rename',
85
+ /** 大世界:提炼 / 保存结构化数据(境界/区域/势力)。 */
86
+ world: '/api/dsh-novel-forge/world',
87
+ /** 封面:GET 读取(dataUrl)/ POST 上传或移除。 */
88
+ cover: '/api/dsh-novel-forge/blurb/cover',
89
+ /** 剧情线管理:增删改 + 关联章节。 */
90
+ plotlines: '/api/dsh-novel-forge/plotlines',
91
+ /** 角色库:提炼 / 采纳 / 更新 / 删除。 */
92
+ roles: '/api/dsh-novel-forge/roles',
93
+ /** 作者复盘补跑:对已写章节补齐 authorReview(全书流式 / 单章 JSON)。 */
94
+ reviewBackfill: '/api/dsh-novel-forge/review/backfill',
95
+ /** 章节复位:generating 卡死 → pending(可重新生成)。 */
96
+ chapterReset: '/api/dsh-novel-forge/chapter/reset',
97
+ /** 章节直接通过:作者对 rejected/written 章节行使最终决定权。 */
98
+ chapterApprove: '/api/dsh-novel-forge/chapter/approve',
99
+ /** 敏感词检查:全书已写章节或指定文本。 */
100
+ sensitiveCheck: '/api/dsh-novel-forge/sensitive-check',
101
+ /** 开书想法 → 补全大纲:输入一句话想法,生成 2-3 个可选大纲方案。 */
102
+ outlineSuggest: '/api/dsh-novel-forge/outline/suggest',
103
+ /** 反推大纲:从已写章节正文反向生成全书总纲(NDJSON 流)。 */
104
+ outlineReverse: '/api/dsh-novel-forge/outline/reverse',
105
+ /** 拆书分析:对已写章节做结构/人物/文风/卖点四维体检(两阶段:源笔记→分节分析)。 */
106
+ breakdown: '/api/dsh-novel-forge/breakdown',
107
+ /** 生产单:启动批量生产(计划补足 + 逐章生成 + 被拒分级处理)。 */
108
+ runStart: '/api/dsh-novel-forge/run/start',
109
+ /** 生产单控制:pause / resume / stop。 */
110
+ runControl: '/api/dsh-novel-forge/run/control',
111
+ /** 生产单状态(含进度统计与日志)。 */
112
+ runStatus: '/api/dsh-novel-forge/run/status',
113
+ config: '/api/dsh-novel-forge/config',
114
+ /** 输出目录迁移:dryRun 预览 / 确认后搬文件并联动配置与书架。 */
115
+ moveOutputDir: '/api/dsh-novel-forge/move-output-dir',
116
+ /** 本书参数:POST {} 读取;POST {patch} 合并保存(存 novel-project.json)。 */
117
+ bookSettings: '/api/dsh-novel-forge/book-settings',
118
+ openFolder: '/api/dsh-novel-forge/open-folder',
119
+ /** 插件自更新:在 DSH profile 目录拉取最新 npm 版(下载后需重启 DSH 生效)。 */
120
+ pluginUpdate: '/api/dsh-novel-forge/plugin/update',
121
+ /** 作者资产库/总数据:读取个人跨书资产(笔法/红线/套路/角色模板/世界观模板)。 */
122
+ authorAssets: '/api/dsh-novel-forge/author-assets',
123
+ /** 作者资产库:新增/更新一条资产(upsert by id)。 */
124
+ authorAssetsUpsert: '/api/dsh-novel-forge/author-assets/upsert',
125
+ /** 作者资产库:删除一条资产。 */
126
+ authorAssetsRemove: '/api/dsh-novel-forge/author-assets/remove',
127
+ /** 作者资产库:导入默认(书架书的写作资产/角色 + 内置全局库)批量沉淀。 */
128
+ authorAssetsImportDefault: '/api/dsh-novel-forge/author-assets/import-default',
129
+ /** 改编模式:上传全文 → 分析 → 原文设定卡片/可改范围矩阵。 */
130
+ adaptAnalyze: '/api/dsh-novel-forge/adapt/analyze',
131
+ /** 改编模式:确认要改的维度 → 生成映射表/改编规则/联动影响清单。 */
132
+ adaptPropose: '/api/dsh-novel-forge/adapt/propose',
133
+ /** 改编模式:执行术语替换(全局替换 + 命中统计 + 改编文本预览)。 */
134
+ adaptExecute: '/api/dsh-novel-forge/adapt/execute',
135
+ /** 改编模式:保存改编全文为新书(原书保留,登记书架)。 */
136
+ adaptSave: '/api/dsh-novel-forge/adapt/save',
137
+ /** 改编模式:从源全文 + 编辑后方案提炼新书资料并保存为「待写新书」。 */
138
+ adaptMaterialize: '/api/dsh-novel-forge/adapt/materialize',
139
+ /** 改编模式:rewrite 逐章重写(NDJSON 流式进度)。 */
140
+ adaptRewriteStream: '/api/dsh-novel-forge/adapt/rewrite-stream',
141
+ /** 改编模式:把预览/微调后的新书资料写入并登记书架。 */
142
+ adaptMaterializeSave: '/api/dsh-novel-forge/adapt/materialize-save',
143
+ /** 主题自定义背景:上传图片(POST,存盘并返回服务端 URL)。 */
144
+ themeBackgroundUpload: '/api/dsh-novel-forge/theme/background',
145
+ /** 主题自定义背景:读取已上传文件(GET prefix,/theme/background/<name>)。 */
146
+ themeBackgroundGet: '/api/dsh-novel-forge/theme/background',
147
+ } as const
148
+
149
+ /** 书架:一本书的条目。 */
150
+ export interface BookEntry {
151
+ /** 稳定 id。 */
152
+ id: string
153
+ /** 书名。 */
154
+ bookName: string
155
+ /** 该书输出目录(独立项目目录)。 */
156
+ outputDir: string
157
+ /** 创建时间。 */
158
+ createdAt: string
159
+ /** 最后活动时间。 */
160
+ updatedAt: string
161
+ }
162
+
163
+ /** 书架快照(含每本书的进度摘要)。 */
164
+ export interface BookshelfSnapshot {
165
+ books: Array<BookEntry & { done: number; total: number; hasProject: boolean; hasCover: boolean; blurb?: string }>
166
+ /** 当前激活的书 id(无则 null)。 */
167
+ activeBookId: string | null
168
+ }
169
+
170
+ /** POST /bookshelf 请求:创建新书。 */
171
+ export interface BookCreateRequest {
172
+ bookName: string
173
+ outputDir?: string
174
+ /** 开书向导:创建时直接导入的大纲文本(提供则立即建立项目)。 */
175
+ outline?: string
176
+ }
177
+
178
+ /** POST /reset 请求:重置项目(可选更新大纲)。 */
179
+ export interface ResetRequest {
180
+ /** 新大纲文本;提供则替换 outline,否则保留原大纲。 */
181
+ outline?: string
182
+ }
183
+
184
+ /** POST /bookshelf/activate 请求:切换当前书。 */
185
+ export interface BookActivateRequest {
186
+ id: string
187
+ }
188
+
189
+ /** POST /bookshelf/remove 请求:移除书架条目。 */
190
+ export interface BookRemoveRequest {
191
+ id: string
192
+ }
193
+
194
+ /** POST /bookshelf/import-dir 请求:导入已有项目目录。 */
195
+ export interface BookImportDirRequest {
196
+ /** 项目目录(须含 novel-project.json)。 */
197
+ outputDir: string
198
+ }
199
+
200
+ /** POST /bookshelf/import-dir 响应。 */
201
+ export interface BookImportDirResponse {
202
+ book: BookEntry
203
+ /** true = 目录已在书架中(本次为重新激活)。 */
204
+ existed: boolean
205
+ }
206
+
207
+ /** POST /bookshelf/import-text 请求:导入 txt/md 全本。两种模式二选一:
208
+ * - filePath:服务器本地文件路径;
209
+ * - text + fileName:浏览器上传的全文内容(fileName 用于推断书名)。
210
+ */
211
+ export interface BookImportTextRequest {
212
+ /** 模式一:源文件绝对路径(txt 或 md)。 */
213
+ filePath?: string
214
+ /** 模式二:浏览器上传的全文内容。 */
215
+ text?: string
216
+ /** 模式二:原文件名(txt/md),用于推断书名与显示。 */
217
+ fileName?: string
218
+ /** 输出目录;缺省为 ~/.dsh/novels/书名。 */
219
+ outputDir?: string
220
+ }
221
+
222
+ /** POST /bookshelf/import-text 响应。 */
223
+ export interface BookImportTextResponse {
224
+ bookName: string
225
+ /** 成功拆出的章节数。 */
226
+ chapters: number
227
+ /** 因内容过短被跳过的章节标题列表。 */
228
+ skipped: string[]
229
+ /** 登记后的书架条目。 */
230
+ book: BookEntry
231
+ }
232
+
233
+ /** POST /bookshelf/import-text/preview 请求:上传全文做拆章预览(不落盘)。 */
234
+ export interface BookImportTextPreviewRequest {
235
+ text: string
236
+ /** 原文件名(txt/md),用于推断书名。 */
237
+ fileName?: string
238
+ }
239
+
240
+ /** POST /bookshelf/import-text/preview 响应。 */
241
+ export interface BookImportTextPreviewResponse {
242
+ /** 预计书名(fileName 去扩展名)。 */
243
+ bookName: string
244
+ /** 识别出的章节(已按正文长度过滤过短章节)。 */
245
+ chapters: Array<{ no: number; title: string; chars: number }>
246
+ /** 因内容过短被跳过的章节标题列表。 */
247
+ skipped: string[]
248
+ }
249
+
250
+ /** Chapter lifecycle states (the writing pipeline's state machine). */
251
+ export type ChapterStatus =
252
+ | 'pending' // planned, not started
253
+ | 'generating' // LLM writing right now
254
+ | 'written' // body on disk, awaiting review
255
+ | 'reviewing' // review in progress
256
+ | 'approved' // passed review (or user-approved)
257
+ | 'rejected' // review found problems
258
+ | 'error' // generation failed
259
+
260
+ /** One chapter in the plan. */
261
+ export interface ChapterPlan {
262
+ /** 1-based chapter number (stable identity; files are named from it). */
263
+ no: number
264
+ /** Volume this chapter belongs to (1-based; 0 = unassigned). */
265
+ volume: number
266
+ /** Chapter title, decided by the LLM plan step. */
267
+ title: string
268
+ /** Story beats / plot points for this chapter (model-facing guidance). */
269
+ beats: string
270
+ /** Target character count (defaults to the configured chapter size). */
271
+ targetChars: number
272
+ /** 本章必达项(必须推进的局面/关系/信息/风险/决策变化)。 */
273
+ mustAdvance?: string[]
274
+ /** 本章必须保持/不得破坏的项(如人物状态、已有伏笔不提前揭)。 */
275
+ mustPreserve?: string[]
276
+ /** 本章不可违背的人物硬事实(身份/阵营/境界/当前位置/知情度)。 */
277
+ characterHardFacts?: string[]
278
+ /** 伏笔操作指令(seed/touch/pressure/partial_reveal/payoff/forbid)。 */
279
+ payoffDirectives?: Array<{ no?: number; operation?: 'seed' | 'touch' | 'pressure' | 'partial_reveal' | 'payoff' | 'forbid'; text?: string }>
280
+ /** 章末钩子要求(悬念/反转/新线索/未闭合选择)。 */
281
+ endingHook?: string
282
+ /** 本章义务合约(人类可读摘要,供生成与审稿共同锚定)。 */
283
+ obligation?: string
284
+ /** Generation/review state. */
285
+ status: ChapterStatus
286
+ /** 进入 generating 的时间(用于超时自动复位;未在生成时无此字段)。 */
287
+ generatingAt?: string
288
+ /** Actual character count once generated. */
289
+ chars?: number
290
+ /** Failure message when status is 'error'. */
291
+ error?: string
292
+ /** Output file name once generated (relative to the output dir). */
293
+ file?: string
294
+ /** LLM summary of the chapter (narrative memory for later chapters). */
295
+ summary?: string
296
+ /** Latest review report (present once reviewed). */
297
+ review?: ReviewReport
298
+ /** 作者复盘:钩子兑现/结尾钩子/剧情线推进/连续性/节奏趋势(生成后自动)。 */
299
+ authorReview?: AuthorReview
300
+ /**
301
+ * 待确认草稿:润色(去AI味)或整章重写的产物正文。生成时先存这里,
302
+ * 用户看过对比后点「采纳」才覆盖正文文件;点「放弃」则丢弃。刷新页面不丢失。
303
+ */
304
+ pendingDraft?: string
305
+ }
306
+
307
+ /** 作者复盘:叙事结构层面的逐章检查(钩子/推进/连续性/趋势)。 */
308
+ export interface AuthorReview {
309
+ /** 上一章结尾钩子是否在本章兑现。 */
310
+ hookHonored: boolean
311
+ /** 钩子兑现说明(未兑现时给出建议)。 */
312
+ hookNote: string
313
+ /** 本章结尾钩子强度 0-10。 */
314
+ endingHook: number
315
+ /** 剧情线推进情况(推进了哪条线/或未推进)。 */
316
+ plotlineProgress: string
317
+ /** 结构化:本章推进的剧情线名称列表(与项目剧情线 name 精确匹配,复盘后自动关联章节)。 */
318
+ advancedLines?: string[]
319
+ /** 连续性检查(人物位置/时间/伤势/资源是否与上章衔接)。 */
320
+ continuity: string
321
+ /** 近期节奏趋势提示(拖沓/爽点密度等)。 */
322
+ trend: string
323
+ /** 本章发生的关键状态变化(人物状态/世界局面/关系/资源),用于回灌整本与事实库。 */
324
+ stateChanges?: string[]
325
+ /** 本章新引入或升级的冲突(供整本控制层与后续卷节奏参考)。 */
326
+ newConflicts?: string[]
327
+ /** 本章埋下/推进的新线索(供知识与伏笔系统回灌)。 */
328
+ clues?: string[]
329
+ /** 本章缺席但值得注意的角色及风险(卷级职责/缺席风险)。 */
330
+ absentRisks?: string[]
331
+ /** 复盘时间。 */
332
+ reviewedAt: string
333
+ }
334
+
335
+ /** 审稿维度(结构化定位问题类别;与 review-policy.ts 的 REVIEW_DIMENSIONS 对齐)。 */
336
+ export type ReviewDimension = 'character' | 'setting' | 'redline' | 'writing' | 'pacing' | 'logic' | 'anti-ai' | 'presentation' | 'compliance'
337
+
338
+ /** One review finding. */
339
+ export interface ReviewIssue {
340
+ /** Severity: high = must fix, medium = should fix, low = suggestion. */
341
+ severity: 'high' | 'medium' | 'low'
342
+ /** 问题维度(可选;缺省由前端按 item 推断)。 */
343
+ dimension?: ReviewDimension
344
+ /** What the problem is. */
345
+ item: string
346
+ /** Concrete suggestion for fixing it. */
347
+ suggestion: string
348
+ /** 命中的反 AI 规则名(结构化,便于统计)。 */
349
+ ruleName?: string
350
+ /** 规则类别:forbidden / risk / encourage。 */
351
+ ruleType?: 'forbidden' | 'risk' | 'encourage'
352
+ /** 问题细分类(如 套话 句式 段落 心理 设定)。 */
353
+ category?: string
354
+ /** 命中的原文摘录。 */
355
+ excerpt?: string
356
+ /** 判定理由。 */
357
+ reason?: string
358
+ /** 是否可自动改写。 */
359
+ canAutoRewrite?: boolean
360
+ }
361
+
362
+ /** AI review report for one chapter. */
363
+ export interface ReviewReport {
364
+ /** Overall score 0-100. */
365
+ score: number
366
+ /** Pass threshold (config; 70 default). */
367
+ passed: boolean
368
+ /** One-line verdict. */
369
+ verdict: string
370
+ /** Individual findings. */
371
+ issues: ReviewIssue[]
372
+ /** 风险分 0-100(越高越需人工处理;源自 LLM 复核与本地扫描)。 */
373
+ riskScore?: number
374
+ /** 本地 AI 味指数 0-100(越高越像 AI;LLM 复核锚点,供 UI 展示)。 */
375
+ aiFlavor?: number
376
+ /** 本地扫描命中的高频套话(按次数降序,取前若干)。 */
377
+ aiPhrases?: Array<{ word: string; count: number }>
378
+ /** When the review ran. */
379
+ reviewedAt: string
380
+ }
381
+
382
+ /** A volume of the book. */
383
+ export interface Volume {
384
+ /** 1-based volume number. */
385
+ no: number
386
+ /** Volume title. */
387
+ title: string
388
+ /** Volume positioning / summary. */
389
+ summary: string
390
+ /** First chapter number of this volume. */
391
+ chapterStart: number
392
+ /** Last chapter number (inclusive). */
393
+ chapterEnd: number
394
+ /** 卷级战略(这一卷的定位/承转,如「立威卷」「冲突升级卷」)。 */
395
+ strategy?: string
396
+ /** 卷节奏板(这一卷的节奏安排:起-承-转-合/爽点密度/关键节点)。 */
397
+ pacing?: string
398
+ }
399
+
400
+ /** 开书定盘:面向读者的承诺与流派定位(生成/规划均可引用)。 */
401
+ export interface BookContract {
402
+ /** 一句话卖点/题材承诺。 */
403
+ promise?: string
404
+ /** 主推进模式名(从推进模式库选)。 */
405
+ primaryModeName?: string
406
+ /** 辅助推进模式名。 */
407
+ secondaryModeNames?: string[]
408
+ /** 整体文风基调(一句话)。 */
409
+ tone?: string
410
+ /** 目标平台(如「番茄」)。 */
411
+ targetPlatform?: string
412
+ }
413
+
414
+ /** 书内知识库文档(供生成/规划时检索注入的参考资料)。 */
415
+ export interface KnowledgeDoc {
416
+ id: string
417
+ title: string
418
+ content: string
419
+ updatedAt: string
420
+ }
421
+
422
+ /** POST /knowledge request:增删改知识库文档。 */
423
+ export interface KnowledgeRequest {
424
+ action: 'add' | 'remove' | 'replace'
425
+ doc?: { id?: string; title: string; content: string }
426
+ id?: string
427
+ }
428
+
429
+ /** POST /book-analysis request。 */
430
+ export interface BookAnalysisRequest {
431
+ text: string
432
+ }
433
+
434
+ /** 书分析/拆书结果。 */
435
+ export interface BookAnalysisResult {
436
+ sellingPoints: string[]
437
+ structure: string[]
438
+ lessons: string[]
439
+ risks: string[]
440
+ }
441
+
442
+ /** POST /idea-inspiration request。 */
443
+ export interface IdeaInspirationRequest {
444
+ idea: string
445
+ count?: number
446
+ }
447
+
448
+ /** 创意灵感结果:多方向开书灵感。 */
449
+ export interface IdeaInspirationResult {
450
+ ideas: Array<{ title: string; hook: string; genre: string; pov: string; payoff: string }>
451
+ }
452
+
453
+ /** POST /director request。 */
454
+ export interface DirectorRequest {
455
+ focus?: string
456
+ }
457
+
458
+ /** 自动导演编排建议(下一卷/阶段编排 + 修复再平衡)。 */
459
+ export interface DirectorAdvice {
460
+ summary: string
461
+ nextArc: string[]
462
+ pacing: string
463
+ risks: string[]
464
+ fixes: string[]
465
+ }
466
+
467
+ /** 自动导演「采纳」后生成的书内待办项。 */
468
+ export interface DirectorTodo {
469
+ id: string
470
+ text: string
471
+ /** 来源:风险 或 修复。 */
472
+ source: 'risk' | 'fix'
473
+ done: boolean
474
+ createdAt: string
475
+ }
476
+
477
+ /** 题材雷达:单条市场信号。 */
478
+ export interface MarketRadarSignal {
479
+ id: string
480
+ kind: 'genre' | 'protagonist' | 'advantage' | 'opening' | 'relationship' | 'title_pattern' | 'opportunity' | 'crowding'
481
+ title: string
482
+ detail: string
483
+ /** 趋势:current / rising / stable / falling。 */
484
+ direction?: 'current' | 'rising' | 'stable' | 'falling'
485
+ /** 是否建议优先考虑。 */
486
+ recommended?: boolean
487
+ }
488
+
489
+ /** 题材雷达:生产底座(引用内置题材/推进模式库,或给出新资产)。 */
490
+ export interface ProductionFoundation {
491
+ genre: { existingId?: string; name: string; description: string; template?: string }
492
+ primaryStoryMode: { existingId?: string; name: string; driver: string; readerExpectation: string }
493
+ secondaryStoryMode?: { existingId?: string; name: string; driver: string; readerExpectation: string }
494
+ }
495
+
496
+ /** 题材雷达:开书创意简报(可执行,严禁照搬具体作品/命名)。 */
497
+ export interface MarketCreativeBrief {
498
+ promptBlock: string
499
+ openingIdea: string
500
+ coreAdvantage: string
501
+ bookSellingPoint: string
502
+ first30ChapterPromise: string
503
+ }
504
+
505
+ /** 题材雷达结果。 */
506
+ export interface MarketRadarResult {
507
+ signals: MarketRadarSignal[]
508
+ productionFoundation: ProductionFoundation
509
+ /** 开书创意简报(可选;用「用信号创作」接口单独生成)。 */
510
+ creativeBrief?: MarketCreativeBrief
511
+ }
512
+
513
+ /** POST /market-radar request。 */
514
+ export interface MarketRadarRequest {
515
+ platform?: string
516
+ genre?: string
517
+ keywords?: string
518
+ feedText?: string
519
+ /** 已扫描的上榜记录(来自真实榜单抓取),用于让分析基于真实榜单证据。 */
520
+ candidates?: Array<{ title: string; author?: string; tags?: string[]; synopsis?: string; category?: string; heatLabel?: string }>
521
+ }
522
+
523
+ /** POST /market-radar/brief request:用选中的信号 + 影响模式生成开书创意。 */
524
+ export interface MarketRadarBriefRequest {
525
+ influenceMode: 'follow_hot' | 'differentiate' | 'light'
526
+ signals: MarketRadarSignal[]
527
+ }
528
+
529
+ /** A character card from the story bible. */
530
+ export interface CharacterCard {
531
+ name: string
532
+ role: 'protagonist' | 'supporting' | 'antagonist' | 'other'
533
+ /** Personality / traits (short lines). */
534
+ traits: string[]
535
+ /** Goals and motivations. */
536
+ goals: string
537
+ /** Key relations to other characters. */
538
+ relations: string
539
+ /** 知情度:该角色已经知道的事实/秘密(未列出的信息该角色不知道)。 */
540
+ knowledge?: string[]
541
+ }
542
+
543
+ /** The structured story bible (worldbuilding extracted from the outline). */
544
+ export interface StoryBible {
545
+ /** Genre + tone tags. */
546
+ genre: string
547
+ /** Worldbuilding rules (power system, geography, factions...). */
548
+ worldRules: string[]
549
+ /** Character cards. */
550
+ characters: CharacterCard[]
551
+ /** Writing red lines (forbidden content / must-avoid tropes). */
552
+ redLines: string[]
553
+ /** Style guidance (pacing, pov, tone). */
554
+ style: string[]
555
+ /** When the bible was generated. */
556
+ generatedAt?: string
557
+ }
558
+
559
+ /** A planted/active/resolved foreshadowing thread. */
560
+ export interface Foreshadow {
561
+ /** Stable id. */
562
+ id: string
563
+ /** What the foreshadow is. */
564
+ description: string
565
+ /** Chapter where it was planted (undefined = planned). */
566
+ plantedChapter?: number
567
+ /** Chapter where it should be paid off. */
568
+ targetChapter?: number
569
+ /** Lifecycle state. */
570
+ status: 'planned' | 'planted' | 'progressing' | 'resolved' | 'abandoned'
571
+ /** Resolution note when resolved. */
572
+ resolvedNote?: string
573
+ }
574
+
575
+ /** 一条已确立的叙事事实(事实库/时间线,注入后续章节生成)。 */
576
+ export interface ChapterFact {
577
+ /** 来源章节号。 */
578
+ chapterNo: number
579
+ /** 事实文本(人物状态/境界资源/关系变化/伏笔落地等)。 */
580
+ text: string
581
+ }
582
+
583
+ /** 一条全书质检发现的问题(一致性矛盾,定位到章)。 */
584
+ export interface AuditIssue {
585
+ /** 问题所在章节号(无法定位时 0)。 */
586
+ chapterNo: number
587
+ severity: 'high' | 'medium' | 'low'
588
+ /** 矛盾描述。 */
589
+ item: string
590
+ /** 修改建议。 */
591
+ suggestion: string
592
+ }
593
+
594
+ /** POST /audit 响应。 */
595
+ export interface AuditResponse {
596
+ issues: AuditIssue[]
597
+ /** 参与质检的章节数。 */
598
+ auditedChapters: number
599
+ /** 质检时间。 */
600
+ auditedAt: string
601
+ /** 本次质检使用的模型(auditModel 或全局 model)。 */
602
+ model?: string
603
+ }
604
+
605
+ /** 全书质检的实时状态(通过 /status 暴露给面板/外部读取)。 */
606
+ export interface AuditStatus {
607
+ status: 'idle' | 'running' | 'done' | 'error'
608
+ /** 开始时间(ISO)。 */
609
+ startedAt?: string
610
+ /** 结束时间(ISO)。 */
611
+ finishedAt?: string
612
+ /** 总批次数(0 = 尚未开始/无章节)。 */
613
+ totalBatches: number
614
+ /** 已完成批次数。 */
615
+ completedBatches: number
616
+ /** 参与质检的章节数。 */
617
+ auditedChapters?: number
618
+ /** 发现的问题数(done 后有效)。 */
619
+ issuesCount?: number
620
+ /** 最近一次质检的问题清单(done 后有效;error 时为空)。 */
621
+ issues?: AuditIssue[]
622
+ /** 失败信息(error 时有效)。 */
623
+ error?: string
624
+ }
625
+
626
+ /** 一条剧情线(主线/支线/人物线/悬念线)。 */
627
+ export interface Plotline {
628
+ /** 稳定 id。 */
629
+ id: string
630
+ /** 线名。 */
631
+ name: string
632
+ /** 类型:主线 / 支线 / 人物线 / 悬念线。 */
633
+ kind: 'main' | 'branch' | 'character' | 'mystery'
634
+ /** 目标/终点(这条线最终要完成什么)。 */
635
+ goal: string
636
+ /** 当前进度说明(最近推进到哪)。 */
637
+ progress: string
638
+ /** 生命周期状态。 */
639
+ status: 'active' | 'paused' | 'resolved' | 'abandoned'
640
+ /** 关联章节号(推进/落地的章节)。 */
641
+ chapters: number[]
642
+ /** 创建时间。 */
643
+ createdAt: string
644
+ }
645
+
646
+ /** POST /plotlines 请求:剧情线增删改 + 关联章节 + AI 辅助。 */
647
+ export interface PlotlinesRequest {
648
+ op: 'add' | 'update' | 'remove' | 'link' | 'suggest' | 'refresh' | 'health' | 'plan'
649
+ /** add / update 时传入的完整剧情线。 */
650
+ line?: Plotline
651
+ /** remove / link / refresh 时的目标线 id。 */
652
+ id?: string
653
+ /** link 时关联的章节号。 */
654
+ chapterNo?: number
655
+ }
656
+
657
+ /** 剧情线健康检查报告。 */
658
+ export interface PlotlineHealthReport {
659
+ /** 是否需要新线(需要 / 暂不需要 / 再写 X 章后需要)。 */
660
+ verdict: string
661
+ /** 建议添加新线的时机说明。 */
662
+ timing: string
663
+ /** 依据(基于数据的理由,每条一句)。 */
664
+ reasons: string[]
665
+ /** 各线健康度。 */
666
+ lines: Array<{
667
+ name: string
668
+ /** ok=健康 / warning=预警 / stale=搁置过久。 */
669
+ health: 'ok' | 'warning' | 'stale'
670
+ note: string
671
+ }>
672
+ }
673
+
674
+ /** 剧情方案:下一阶段目标 + 建议新线。 */
675
+ export interface PlotlinePlan {
676
+ /** 下一阶段(未来 5-10 章)剧情方向。 */
677
+ direction: string
678
+ /** 建议的新线(可逐条采纳)。 */
679
+ suggestions: Plotline[]
680
+ }
681
+
682
+ /** POST /plotlines 响应。 */
683
+ export interface PlotlinesResponse {
684
+ plotlines: Plotline[]
685
+ /** op=suggest 时的 建议候选线。 */
686
+ suggestions?: Plotline[]
687
+ /** op=health 时的健康检查报告。 */
688
+ health?: PlotlineHealthReport
689
+ /** op=plan 时的剧情方案。 */
690
+ plan?: PlotlinePlan
691
+ }
692
+
693
+ /** 一条敏感词命中。 */
694
+ export interface SensitiveHit {
695
+ /** 命中章节号(文本检测时为 0)。 */
696
+ chapterNo: number
697
+ /** 命中的违禁词。 */
698
+ word: string
699
+ /** 类别:政治 / 擦边 / 暴力 / 辱骂 / 广告 / 其他。 */
700
+ category: string
701
+ /** 出现次数。 */
702
+ count: number
703
+ }
704
+
705
+ /** POST /sensitive-check 请求:检测指定章节/任意文本/全书。 */
706
+ export interface SensitiveCheckRequest {
707
+ /** 检测该章正文。 */
708
+ chapterNo?: number
709
+ /** 检测任意文本(优先于 chapterNo)。 */
710
+ text?: string
711
+ /** 扫描全部已写章节。 */
712
+ all?: boolean
713
+ }
714
+
715
+ /** POST /sensitive-check 响应。 */
716
+ export interface SensitiveCheckResponse {
717
+ hits: SensitiveHit[]
718
+ /** 参与扫描的章节数。 */
719
+ scannedChapters: number
720
+ }
721
+
722
+ /** 开书想法 → AI 大纲方案(一个候选)。 */
723
+ export interface OutlineCandidate {
724
+ /** 唯一 id(前端暂留/换批用)。 */
725
+ id: string
726
+ /** 推荐书名。 */
727
+ bookName: string
728
+ /** 题材(如 仙侠修真 / 都市)。 */
729
+ genre: string
730
+ /** 核心卖点一句话。 */
731
+ sellingPoint: string
732
+ /** 完整大纲文本(可直接用作项目大纲,≥800 字)。 */
733
+ outline: string
734
+ }
735
+
736
+ /** POST /outline/suggest 请求:想法 → 2-3 个可选大纲。 */
737
+ export interface OutlineSuggestRequest {
738
+ /** 作者想法(一两句话,≥50 字)。 */
739
+ idea: string
740
+ /** 本次要生成的候选数(默认 3,最多 3)。 */
741
+ count?: number
742
+ /** 已暂留方案的剧情方向摘要(换批时让 LLM 避开,防止与已留方案重复)。 */
743
+ exclude?: string[]
744
+ }
745
+
746
+ /** POST /outline/suggest 响应。 */
747
+ export interface OutlineSuggestResponse {
748
+ candidates: OutlineCandidate[]
749
+ }
750
+
751
+ /** 拆书分析:一个分析小节。 */
752
+ export interface BreakdownSection {
753
+ /** 小节键:overview / plot / character / style / market。 */
754
+ key: string
755
+ /** 小节标题(如「拆书总览」)。 */
756
+ title: string
757
+ /** 可读分析稿(markdown)。 */
758
+ markdown: string
759
+ /** 结构化数据(程序可消费)。 */
760
+ structured: Record<string, unknown>
761
+ }
762
+
763
+ /** 拆书分析:一条证据(结论→原文回溯)。 */
764
+ export interface BreakdownEvidence {
765
+ label: string
766
+ excerpt: string
767
+ /** 来源章节号(0 = 未定位)。 */
768
+ chapterNo: number
769
+ /** 指向的结构化字段。 */
770
+ fieldKey?: string
771
+ }
772
+
773
+ /** POST /breakdown 请求:对已写章节做拆书分析。 */
774
+ export interface BreakdownRequest {
775
+ /** 分析范围:'recent'=最近 20 章 / 'volume:N'=第 N 卷 / 'all'=全书(默认 recent)。 */
776
+ scope?: string
777
+ /** 分析档位:'quick'=4 维(总览/剧情/人物/文风)/ 'standard'=5 维(+卖点)。 */
778
+ preset?: 'quick' | 'standard'
779
+ /** token 预算上限(默认 50000)。 */
780
+ budgetTokens?: number
781
+ }
782
+
783
+ /** POST /breakdown 响应。 */
784
+ export interface BreakdownResponse {
785
+ sections: BreakdownSection[]
786
+ evidence: BreakdownEvidence[]
787
+ /** 参与分析的章节数。 */
788
+ chaptersScanned: number
789
+ /** 估算消耗 token。 */
790
+ usedTokens: number
791
+ }
792
+
793
+ /** 角色卡:角色当前状态(从事实库聚合)。 */
794
+ export interface RoleStatusCard {
795
+ name: string
796
+ /** protagonist / supporting / antagonist / other。 */
797
+ role: string
798
+ /** 当前状态一句话(境界/资源/伤势/心境)。 */
799
+ status: string
800
+ /** 最近出场章节。 */
801
+ lastChapter: number
802
+ /** 出场次数。 */
803
+ appearances: number
804
+ }
805
+
806
+ /** 角色库条目(主表:作者维护 + 提炼 + 编年录自动聚合)。 */
807
+ export interface RoleRecord {
808
+ /** 角色名(唯一键)。 */
809
+ name: string
810
+ /** 定位:主角 / 女主 / 女配 / 配角 / 反派 / 路人。 */
811
+ roleLabel: 'protagonist' | 'female_lead' | 'female_support' | 'support' | 'antagonist' | 'extra'
812
+ /** 身份一句话(如:祭族后裔、青云宗杂役)。 */
813
+ identity: string
814
+ /** 性格标签。 */
815
+ traits: string[]
816
+ /** 目标与动机。 */
817
+ goals: string
818
+ /** 关系网:[角色名](关系)。 */
819
+ relations: string[]
820
+ /** 成长线:阶段 → 说明(可含章节)。 */
821
+ arc: string[]
822
+ /** 知情度:该角色已经知道的信息。 */
823
+ knowledge: string[]
824
+ /** 首次出场章节(编年录聚合,可手动修正)。 */
825
+ firstChapter?: number
826
+ }
827
+
828
+ /** POST /roles 请求:角色库增删改 + 提炼 + 参考图上传。 */
829
+ export interface RolesRequest {
830
+ op: 'extract' | 'adopt' | 'update' | 'remove'
831
+ /** adopt / update 时传入的角色(adopt 可修改后采纳)。 */
832
+ role?: RoleRecord
833
+ /** remove 时的角色名。 */
834
+ name?: string
835
+ }
836
+
837
+
838
+ /** POST /llm-test 请求:对选中的提供商/模型发一次最小真实调用。 */
839
+ export interface LlmTestRequest {
840
+ provider: string
841
+ model: string
842
+ }
843
+
844
+ /** POST /llm-test 响应。 */
845
+ export interface LlmTestResponse {
846
+ ok: boolean
847
+ /** 连通延迟(毫秒)。 */
848
+ ms?: number
849
+ /** 失败原因(已映射为人话)。 */
850
+ message?: string
851
+ /** 稳定错误码(LlmError code),便于排查。 */
852
+ code?: string
853
+ }
854
+
855
+ /** POST /roles 响应。 */
856
+ export interface RolesResponse {
857
+ roles: RoleRecord[]
858
+ /** op=extract 时的 AI 候选角色。 */
859
+ candidates?: RoleRecord[]
860
+ }
861
+
862
+ /** POST /bible/patch 请求:局部修补道藏。 */
863
+ export interface BiblePatchRequest {
864
+ worldRules?: string[]
865
+ redLines?: string[]
866
+ style?: string[]
867
+ /** 角色卡整体替换(人物志编辑知情度等)。 */
868
+ characters?: CharacterCard[]
869
+ }
870
+
871
+ /** POST /blurb 请求:生成/补全或手动保存小说简介。 */
872
+ export interface BlurbRequest {
873
+ action: 'generate' | 'save'
874
+ /** 已写好的开头(补全时使用;留空 = 全量生成)。 */
875
+ partial?: string
876
+ /** 手动保存的完整简介(action=save 时)。 */
877
+ text?: string
878
+ }
879
+
880
+ /** POST /chapter/check|save 请求:审查/保存手动编辑的正文。 */
881
+ export interface ChapterTextRequest {
882
+ chapterNo: number
883
+ /** 当前编辑中的正文全文。 */
884
+ text: string
885
+ /** 保存时携带:已在工作区审查过的报告(沿用落盘,不重复审);缺省则保存后自动正式审稿一次。 */
886
+ report?: ReviewReport
887
+ /** 审查/验证时携带:上一轮审稿报告。传入后进入「验证模式」——逐条核对原意见是否解决、
888
+ * 只挑新增 high,不再全新找茬(防止"越修 high 越多")。 */
889
+ previousReport?: ReviewReport
890
+ }
891
+
892
+ /** POST /chapter/save 响应。 */
893
+ export interface ChapterSaveResponse {
894
+ ok: boolean
895
+ chars: number
896
+ file: string
897
+ /** 落盘的审稿报告(沿用工作区报告或保存后自动审稿)。 */
898
+ report?: ReviewReport
899
+ }
900
+
901
+ /** POST /cover 请求:上传或移除封面。 */
902
+ export interface CoverRequest {
903
+ action: 'upload' | 'remove'
904
+ /** 上传时:data:image/...;base64,... 格式的图片数据。 */
905
+ dataUrl?: string
906
+ }
907
+
908
+ /** POST /rename 请求:重命名当前书。 */
909
+ export interface RenameRequest {
910
+ bookName: string
911
+ }
912
+
913
+ /** 大世界:一个境界等级。 */
914
+ export interface WorldRealm {
915
+ /** 境界名(练气/筑基/金丹…)。 */
916
+ name: string
917
+ /** 描述:突破条件/寿命/标志等。 */
918
+ description: string
919
+ }
920
+
921
+ /** 大世界:一个地理区域。 */
922
+ export interface WorldRegion {
923
+ name: string
924
+ description: string
925
+ /** 关联势力名(可空)。 */
926
+ faction?: string
927
+ }
928
+
929
+ /** 大世界:一方势力。 */
930
+ export interface WorldFaction {
931
+ name: string
932
+ /** 类型:宗门/家族/王朝/组织… */
933
+ kind: string
934
+ description: string
935
+ /** 驻地区域(可空)。 */
936
+ region?: string
937
+ }
938
+
939
+ /** 大世界结构化数据。 */
940
+ export interface WorldState {
941
+ realms: WorldRealm[]
942
+ regions: WorldRegion[]
943
+ factions: WorldFaction[]
944
+ }
945
+
946
+ /** POST /world 请求:提炼或手动保存。 */
947
+ export interface WorldRequest {
948
+ action: 'generate' | 'save'
949
+ /** action=save 时的完整世界数据。 */
950
+ world?: WorldState
951
+ }
952
+
953
+ /** GET /cover 响应:封面的 dataUrl(无封面为 null)。 */
954
+ export interface CoverResponse {
955
+ dataUrl: string | null
956
+ }
957
+
958
+ /** The persisted project: outline + bible + plan + progress. */
959
+ export interface ProjectState {
960
+ /** Book title (first non-empty line of the outline, usually). */
961
+ bookName: string
962
+ /** Full outline text (docx-extracted or pasted). */
963
+ outline: string
964
+ /** Source outline path when loaded from a docx. */
965
+ outlinePath?: string
966
+ /** Structured story bible (worldbuilding), if generated. */
967
+ bible?: StoryBible
968
+ /** Volumes, if planned. */
969
+ volumes?: Volume[]
970
+ /** Chapter plan. */
971
+ chapters: ChapterPlan[]
972
+ /** Foreshadowing threads. */
973
+ foreshadows: Foreshadow[]
974
+ /** 写作资产(题材基底/推进模式/反AI规则/写法资产)。 */
975
+ assets?: ProjectAssets
976
+ /** 事实库/时间线:每章生成后抽取,注入后续章节保持一致性。 */
977
+ facts?: ChapterFact[]
978
+ /** 书内知识库文档(可检索资料/设定/参考)。 */
979
+ knowledgeDocs?: KnowledgeDoc[]
980
+ /** 自动导演待办:风险/修复「采纳」后生成的随手清单。 */
981
+ todos?: DirectorTodo[]
982
+ /** 小说简介(面向读者的作品门面,生成或手动保存)。 */
983
+ blurb?: string
984
+ /** 开书定盘:书籍级承诺与流派定位(前30章承诺/主副模式/文风/平台)。 */
985
+ bookContract?: BookContract
986
+ /** 封面文件名(相对输出目录,如 cover.png)。 */
987
+ coverPath?: string
988
+ /** 大世界结构化数据(境界体系/区域/势力)。 */
989
+ world?: WorldState
990
+ /** 剧情线(主线/支线/人物线/悬念线)。 */
991
+ plotlines?: Plotline[]
992
+ /** 角色库(作者维护 + 提炼的主表)。 */
993
+ roles?: RoleRecord[]
994
+ /** 人物志:角色当前状态聚合结果(从编年录刷新后存档,打开页面直接显示)。 */
995
+ roleStatus?: RoleStatusCard[]
996
+ /** 本书参数(写作/审稿/推理/模型快切;未设字段回退全局 config)。 */
997
+ bookSettings?: BookSettings
998
+ /** ISO timestamps. */
999
+ createdAt: string
1000
+ updatedAt: string
1001
+ }
1002
+
1003
+ /** 本书参数(存 novel-project.json.bookSettings;未设字段回退全局 config)。 */
1004
+ export interface BookSettings {
1005
+ /** 本书使用的提供方路由(快切器写入)。 */
1006
+ provider?: string
1007
+ /** 本书使用的主模型 id。 */
1008
+ model?: string
1009
+ /** 本书写作推理档位。 */
1010
+ reasoningEffort?: 'off' | 'low' | 'high' | 'max'
1011
+ /** 本书分析类任务推理档位。 */
1012
+ analysisReasoning?: 'off' | 'low' | 'high' | 'max'
1013
+ /** 本书每章目标字数。 */
1014
+ chapterChars?: number
1015
+ /** 本书单章最大输出 tokens。 */
1016
+ maxTokens?: number
1017
+ /** 本书审稿通过分。 */
1018
+ reviewPassScore?: number
1019
+ /** 本书是否写完自动审稿。 */
1020
+ autoReview?: boolean
1021
+ /** 本书是否自动作者复盘。 */
1022
+ autoAuthorReview?: boolean
1023
+ /** 本书是否修稿后自动复审。 */
1024
+ autoReviewAfterRevise?: boolean
1025
+ }
1026
+
1027
+ /** 手动添加的模型库条目(只存插件内,不改 DSH 全局)。 */
1028
+ export interface SavedModel {
1029
+ /** 唯一 id(前端生成的短 id)。 */
1030
+ id: string
1031
+ /** 展示名(可为空,回退到 model)。 */
1032
+ name: string
1033
+ /** DSH 提供商路由(如 zai-coding-cn)。 */
1034
+ provider: string
1035
+ /** 模型 id(如 glm-5.3-flash)。 */
1036
+ model: string
1037
+ }
1038
+
1039
+ /** DSH 模型添加:厂商预设(选择厂商,直接填 API Key)。 */
1040
+ export interface LlmVendor {
1041
+ id: string
1042
+ name: string
1043
+ /** 该厂商对应的 provider 路由。 */
1044
+ route: string
1045
+ /** DSH 凭据引用名(写入 .credentials.yaml 的 refs)。 */
1046
+ apiKeyEnv: string
1047
+ /** 默认模型 id。 */
1048
+ defaultModel: string
1049
+ /** 建议可选模型 id 列表(下拉 data-list 用)。 */
1050
+ models: string[]
1051
+ /** 内置适配器(如 deepseek-official),无需注册 pi-ai 路由。 */
1052
+ builtin?: boolean
1053
+ }
1054
+
1055
+ /** 预置的常见厂商(id=provider 路由;添加模型下拉兜底用,其余厂商由运行时目录动态补充)。 */
1056
+ export const LLM_VENDORS: LlmVendor[] = [
1057
+ // 注意:本列表只是「运行时目录不可用」时的兜底建议值;实际以 ctx.llm.listModels() 为准
1058
+ // (见 engine.ts listLlmVendors),避免 DSH 侧模型改名后这里的条目过期。
1059
+ { id: 'deepseek-official', name: 'DeepSeek', route: 'deepseek-official', apiKeyEnv: 'DEEPSEEK_API_KEY', defaultModel: 'deepseek-flash', models: ['deepseek-flash', 'deepseek-v4-pro'], builtin: true },
1060
+ { id: 'zai-coding-cn', name: '智谱 GLM', route: 'zai-coding-cn', apiKeyEnv: 'ZAI_CODING_CN_API_KEY', defaultModel: 'glm-5.3-flash', models: ['glm-4.5-air', 'glm-4.7', 'glm-5-turbo', 'glm-5.1', 'glm-5.2', 'glm-5.3', 'glm-5.3-flash', 'glm-5v-turbo'] },
1061
+ { id: 'qwen-token-plan-cn', name: '千问百炼', route: 'qwen-token-plan-cn', apiKeyEnv: 'QWEN_TOKEN_PLAN_CN_API_KEY', defaultModel: 'qwen3.7-max', models: ['qwen3.6-flash', 'qwen3.6-plus', 'qwen3.7-max', 'qwen3.7-plus', 'qwen3.8-max', 'qwen3.8-max-preview'] },
1062
+ { id: 'openrouter', name: 'OpenRouter', route: 'openrouter', apiKeyEnv: 'OPENROUTER_API_KEY', defaultModel: 'z-ai/glm-5.3-flash', models: ['z-ai/glm-4.6', 'z-ai/glm-4.7', 'z-ai/glm-5', 'z-ai/glm-5-turbo', 'z-ai/glm-5.1', 'z-ai/glm-5.2', 'z-ai/glm-5.3-flash', 'auto', 'deepseek/deepseek-v4-flash', 'anthropic/claude-sonnet-4.6'] },
1063
+ ]
1064
+
1065
+ /** 运行时厂商目录的一项(添加到模型下拉;由 DSH 的 pi-ai 可配置提供方动态生成)。 */
1066
+ export interface LlmVendorOption {
1067
+ /** provider 路由 id(也是厂商下拉的值)。 */
1068
+ id: string
1069
+ /** 展示名。 */
1070
+ name: string
1071
+ /** 建议模型 id(可为空,用户手填)。 */
1072
+ models: string[]
1073
+ /** 已知 DSH 凭据引用名;为空时 host 生成 `PI_AI_<ID>_API_KEY`。 */
1074
+ apiKeyEnv?: string
1075
+ /** 内置适配器(只写凭据,不注册 pi-ai 路由)。 */
1076
+ builtin?: boolean
1077
+ }
1078
+
1079
+ /** GET /llm-vendors 响应。 */
1080
+ export interface LlmVendorsResponse {
1081
+ vendors: LlmVendorOption[]
1082
+ }
1083
+
1084
+ /** /llm-models 里的一条模型。 */
1085
+ export interface LlmModelOption { id: string; name: string }
1086
+
1087
+ /** GET /llm-models?provider=x 响应。 */
1088
+ export interface LlmModelsResponse {
1089
+ models: LlmModelOption[]
1090
+ }
1091
+
1092
+ /** GET /llm-providers 响应:当前已注册的提供方路由。 */
1093
+ export interface LlmProvidersResponse {
1094
+ providers: { id: string; name: string }[]
1095
+ }
1096
+
1097
+ /** POST /llm-remove 请求:移除一个提供方(unset key + 移除 llm-pi-ai 路由)。 */
1098
+ export interface RemoveProviderRequest {
1099
+ provider: string
1100
+ /** 该提供方对应的 DSH 凭据引用名(用于 unset)。 */
1101
+ apiKeyEnv?: string
1102
+ }
1103
+
1104
+ /** POST /llm-remove 响应。 */
1105
+ export interface RemoveProviderResponse {
1106
+ ok: boolean
1107
+ message?: string
1108
+ }
1109
+
1110
+ /** POST /llm-add 请求:添加一个模型(厂商直填 key,或自定义路由)。 */
1111
+ export interface AddModelRequest {
1112
+ mode: 'vendor' | 'custom'
1113
+ /** 厂商模式用:provider 路由 id(来自 /llm-vendors)。 */
1114
+ vendor?: string
1115
+ /** 厂商已知的 DSH 凭据引用名(可选;为空时 host 生成)。 */
1116
+ apiKeyEnv?: string
1117
+ /** 自定义模式用:provider 路由 id。 */
1118
+ provider?: string
1119
+ /** 模型 id。 */
1120
+ model: string
1121
+ /** API Key。 */
1122
+ apiKey: string
1123
+ /** 展示名(可选)。 */
1124
+ name?: string
1125
+ /** 自定义模式用:OpenAI 兼容 base URL。 */
1126
+ baseURL?: string
1127
+ }
1128
+
1129
+ /** POST /llm-add 响应。 */
1130
+ export interface AddModelResponse {
1131
+ ok: boolean
1132
+ saved: SavedModel
1133
+ provider: string
1134
+ message?: string
1135
+ }
1136
+
1137
+ /** 手动添加的模型库条目(只存插件内,不改 DSH 全局)。 */
1138
+ export interface NovelConfig {
1139
+ /** Absolute path of the default docx outline to load. */
1140
+ outlinePath: string
1141
+ /** Absolute output directory for chapters + project state. */
1142
+ outputDir: string
1143
+ /** LLM provider route (e.g. deepseek-official). */
1144
+ provider: string
1145
+ /** LLM model id (e.g. deepseek-flash). */
1146
+ model: string
1147
+ /** 生成正文用模型(缺省用 model)。 */
1148
+ generateModel?: string
1149
+ /** 审稿用模型(缺省用 model;建议用更强的 reasoner/pro)。 */
1150
+ reviewModel?: string
1151
+ /** 全书质检(审计)用模型(缺省用 model)。 */
1152
+ auditModel?: string
1153
+ /** LLM reasoning effort: off = no thinking; low/high/max = thinking intensity. */
1154
+ reasoningEffort: 'off' | 'low' | 'high' | 'max'
1155
+ /** 分析类任务(提炼/拆书/反推大纲等)的推理档位;默认 low,不受上面写作档位影响。 */
1156
+ analysisReasoning: 'off' | 'low' | 'high' | 'max'
1157
+ /** Target characters per chapter. */
1158
+ chapterChars: number
1159
+ /** Max output tokens per chapter call. */
1160
+ maxTokens: number
1161
+ /** Review pass threshold (0-100). */
1162
+ reviewPassScore: number
1163
+ /** Whether generation auto-runs review after writing. */
1164
+ autoReview: boolean
1165
+ /** Whether generation auto-runs the author review (hook/continuity/trend) after writing. */
1166
+ autoAuthorReview: boolean
1167
+ /** 修订/润色产出草稿后是否自动附带一次 AI 审查(工作区显示新稿评分与剩余问题)。 */
1168
+ autoReviewAfterRevise: boolean
1169
+ /** 自定义背景图(URL 或 dataURL 或服务端路径引用;空 = 使用主题默认背景)。 */
1170
+ themeBackground?: string
1171
+ /** 自定义背景遮罩/模糊强度 0-80(0 = 不遮罩)。 */
1172
+ themeBackgroundBlur?: number
1173
+ /** 玻璃透明度 0-100(100=当前原样,越小越透,新拟态/黏土可见背景图)。 */
1174
+ themeOpacity?: number
1175
+ /** 是否启用改编模式(默认关闭;发布后开启)。 */
1176
+ enableAdaptMode?: boolean
1177
+ /** 手动添加的模型库(「我的模型」条目;只存插件内)。 */
1178
+ savedModels?: SavedModel[]
1179
+ }
1180
+
1181
+ /** POST /move-output-dir request:dryRun=true 仅预览;确认时须带 to。 */
1182
+ export interface MoveOutputDirRequest {
1183
+ /** 新输出目录(绝对路径)。 */
1184
+ to?: string
1185
+ /** 只列出当前目录内容,不搬移。 */
1186
+ dryRun?: boolean
1187
+ }
1188
+
1189
+ /** POST /move-output-dir response。 */
1190
+ export interface MoveOutputDirResponse {
1191
+ from: string
1192
+ to?: string
1193
+ /** 当前(或迁移后)目录内容清单。 */
1194
+ files: string[]
1195
+ bytes: number
1196
+ /** 联动重指向的书架条目数。 */
1197
+ movedBooks: number
1198
+ /** settings 默认输出目录是否同步更新。 */
1199
+ defaultUpdated: boolean
1200
+ }
1201
+
1202
+ /** POST /book-settings request:patch 省略 = 读取;字段传 null = 删除本书覆盖(回退全局)。 */
1203
+ export interface BookSettingsRequest {
1204
+ patch?: { [K in keyof BookSettings]?: BookSettings[K] | null }
1205
+ }
1206
+
1207
+ /** POST /book-settings response。 */
1208
+ export interface BookSettingsResponse {
1209
+ /** 本书已设置的参数(未设字段缺省 = 回退全局)。 */
1210
+ settings: BookSettings
1211
+ /** 应用回退链后的生效配置(全局 + 本书覆盖)。 */
1212
+ effective: NovelConfig
1213
+ /** 当前是否有打开的书。 */
1214
+ hasBook: boolean
1215
+ }
1216
+
1217
+ /** GET /status response. */
1218
+ /**
1219
+ * 创作阶段契约(宿主计算的「当前阶段 → 本轮允许的动作」)。
1220
+ * 计算逻辑在 stage-contract.ts;这里是宿主与面板/助手共享的线上形状。
1221
+ */
1222
+ export interface StageInfo {
1223
+ /** 阶段标识。 */
1224
+ id: 'outline' | 'bible' | 'plan' | 'write' | 'wait' | 'review' | 'revise' | 'export'
1225
+ /** 中文阶段名。 */
1226
+ label: string
1227
+ /** 建议的下一步动作(助手工具名;无对应工具时为空数组)。 */
1228
+ recommend: string[]
1229
+ /** 本阶段允许的写操作(作者只说了「继续」时的唯一命令集)。 */
1230
+ allow: string[]
1231
+ /** 为什么处于该阶段。 */
1232
+ reason: string
1233
+ }
1234
+
1235
+ export interface StatusResponse {
1236
+ config: NovelConfig
1237
+ /** The persisted project, when one exists in the output dir. */
1238
+ project?: ProjectState
1239
+ /** Chapter files already on disk (basenames, sorted). */
1240
+ generatedFiles: string[]
1241
+ /** 全书质检实时状态(用于面板/外部读取进度)。 */
1242
+ audit?: AuditStatus
1243
+ /** 宿主按项目真实状态算出的创作阶段(面板角标 / 外部自动化共用)。 */
1244
+ stage?: StageInfo
1245
+ /**
1246
+ * 截断声明:本次响应中被裁掉的字段说明(如「编年录:共 320 条,仅返回最近 80 条」)。
1247
+ * 消费方不得把缺失字段当作"不存在",需要完整数据时走专用接口。
1248
+ */
1249
+ truncations?: string[]
1250
+ }
1251
+
1252
+ /** 生产单状态(生产单 = 区间批量生产执行器:计划补足 + 逐章生成 + 被拒分级处理)。 */
1253
+ export interface RunState {
1254
+ runId: string
1255
+ /** 区间起点(含)。 */
1256
+ startNo: number
1257
+ /** 区间终点(含)。 */
1258
+ endNo: number
1259
+ status: 'running' | 'paused' | 'done' | 'stopped' | 'error'
1260
+ /** 当前处理到的章号(已 approved 的章会快进)。 */
1261
+ currentNo: number
1262
+ stats: {
1263
+ /** 新生成(含审稿)的章数。 */
1264
+ generated: number
1265
+ /** 被拒后按意见修订并通过的章数。 */
1266
+ revised: number
1267
+ /** 被拒后豁免通过(无 high)的章数。 */
1268
+ exempted: number
1269
+ /** error 后重新生成的章数。 */
1270
+ regenerated: number
1271
+ /** 生成失败的章数。 */
1272
+ error: number
1273
+ }
1274
+ /** 两轮修订仍不过、保留草稿待人工的章号。 */
1275
+ pendingManual: number[]
1276
+ /** 运行日志(保留最近 300 条)。 */
1277
+ log: Array<{ at: string; text: string }>
1278
+ startedAt: string
1279
+ updatedAt: string
1280
+ error?: string
1281
+ }
1282
+
1283
+ /** POST /run/start request. */
1284
+ export interface RunStartRequest {
1285
+ /** 起始章号(默认 1)。 */
1286
+ startNo?: number
1287
+ /** 结束章号(含;超出计划时自动补计划)。 */
1288
+ endNo?: number
1289
+ /** 或指定新增章数(从当前最后一章 +1 起)。 */
1290
+ count?: number
1291
+ }
1292
+
1293
+ /** POST /run/control request. */
1294
+ export interface RunControlRequest {
1295
+ action: 'pause' | 'resume' | 'stop'
1296
+ }
1297
+
1298
+ /** POST /load-outline request: either a docx path or raw text. */
1299
+ export interface LoadOutlineRequest {
1300
+ /** Absolute docx path; defaults to the configured outline path. */
1301
+ path?: string
1302
+ /** Raw outline text (takes precedence over path when present). */
1303
+ text?: string
1304
+ }
1305
+
1306
+ /** POST /load-outline response. */
1307
+ export interface LoadOutlineResponse {
1308
+ outline: string
1309
+ bookName: string
1310
+ chars: number
1311
+ path?: string
1312
+ }
1313
+
1314
+ /** POST /plan request. */
1315
+ export interface PlanRequest {
1316
+ /** Outline to plan from; defaults to the persisted project's outline. */
1317
+ outline?: string
1318
+ /** Number of chapters to plan (default: 30). */
1319
+ chapterCount?: number
1320
+ /** Volume to plan (1-based); when given, plans only that volume's chapters. */
1321
+ volume?: number
1322
+ }
1323
+
1324
+ /** POST /plan response. */
1325
+ export interface PlanResponse {
1326
+ chapters: ChapterPlan[]
1327
+ volumes?: Volume[]
1328
+ }
1329
+
1330
+ /** POST /volumes request/response. */
1331
+ export interface VolumesRequest {
1332
+ /** Outline to split into volumes; defaults to the project outline. */
1333
+ outline?: string
1334
+ }
1335
+ export interface VolumesResponse {
1336
+ volumes: Volume[]
1337
+ }
1338
+
1339
+ /** POST /bible request/response. */
1340
+ export interface BibleRequest {
1341
+ /** Outline to extract from; defaults to the project outline. */
1342
+ outline?: string
1343
+ }
1344
+ export interface BibleResponse {
1345
+ bible: StoryBible
1346
+ }
1347
+
1348
+ /** POST /generate request: one chapter of the current project. */
1349
+ export interface GenerateRequest {
1350
+ chapterNo: number
1351
+ /** When true, skips the auto-review step. */
1352
+ skipReview?: boolean
1353
+ }
1354
+
1355
+ /** One NDJSON frame of a generation/review/rewrite stream. */
1356
+ export type JobFrame =
1357
+ | { type: 'start'; no: number; title: string }
1358
+ | { type: 'delta'; text: string }
1359
+ | { type: 'progress'; chars: number }
1360
+ | { type: 'done'; no: number; file: string; chars: number; title: string; warn?: string }
1361
+ | { type: 'review'; no: number; report: ReviewReport }
1362
+ | { type: 'author-review'; no: number; review: AuthorReview }
1363
+ | { type: 'author-backfill-done'; count: number }
1364
+ | { type: 'rewritten'; no: number; file: string; chars: number }
1365
+ /** 润色/重写完成,产物作为待确认草稿(尚未覆盖正文)。 */
1366
+ | { type: 'drafted'; no: number; chars: number; draft: string }
1367
+ | { type: 'outline-progress'; done: number; total: number; phase: string }
1368
+ | { type: 'outline-done'; outline: string; chars: number }
1369
+ | { type: 'error'; no: number; message: string }
1370
+
1371
+ /** POST /review request: review one written chapter. */
1372
+ export interface ReviewRequest {
1373
+ chapterNo: number
1374
+ }
1375
+
1376
+ /** POST /rewrite request: rewrite one chapter (optionally per review issues). */
1377
+ export interface RewriteRequest {
1378
+ chapterNo: number
1379
+ /** Free-form instructions; defaults to fixing the review's high issues. */
1380
+ instructions?: string
1381
+ /**
1382
+ * 局部修订:正文中的一段原文(无需完全精确,取一个自然段内的片段即可)。
1383
+ * 提供时只重写该段,其余正文保持不变;不提供时整章重写。
1384
+ */
1385
+ target?: string
1386
+ }
1387
+
1388
+ /** POST /polish request: de-AI-ify one chapter. */
1389
+ export interface PolishRequest {
1390
+ chapterNo: number
1391
+ }
1392
+
1393
+ /** POST /draft/apply | /draft/discard request: 采纳或放弃待确认草稿。 */
1394
+ export interface DraftDecisionRequest {
1395
+ chapterNo: number
1396
+ /** apply 时可携带审查报告(沿用结论定状态;不携带则置 written)。 */
1397
+ report?: ReviewReport
1398
+ }
1399
+
1400
+ /** POST /summary request: (re)generate a chapter summary. */
1401
+ export interface SummaryRequest {
1402
+ chapterNo: number
1403
+ }
1404
+
1405
+ /** POST /foreshadow request: create, update, or AI-suggest foreshadows. */
1406
+ export interface ForeshadowRequest {
1407
+ /** When true, runs the LLM suggestion pass (ignores other fields). */
1408
+ suggest?: boolean
1409
+ /** When given, updates that foreshadow instead of creating one. */
1410
+ id?: string
1411
+ description?: string
1412
+ plantedChapter?: number
1413
+ targetChapter?: number
1414
+ status?: Foreshadow['status']
1415
+ resolvedNote?: string
1416
+ }
1417
+ export interface ForeshadowResponse {
1418
+ foreshadows: Foreshadow[]
1419
+ }
1420
+
1421
+ /** GET /chapter response. */
1422
+ export interface ChapterResponse {
1423
+ no: number
1424
+ title: string
1425
+ markdown: string
1426
+ }
1427
+
1428
+ /** POST /export request/response. */
1429
+ export interface ExportRequest {
1430
+ format: 'txt' | 'md'
1431
+ }
1432
+ export interface ExportResponse {
1433
+ file: string
1434
+ chars: number
1435
+ chapters: number
1436
+ }
1437
+
1438
+ /** POST /config request: patch any subset of the runtime config. */
1439
+ export interface ConfigPatch {
1440
+ outlinePath?: string
1441
+ outputDir?: string
1442
+ provider?: string
1443
+ model?: string
1444
+ generateModel?: string
1445
+ reviewModel?: string
1446
+ auditModel?: string
1447
+ reasoningEffort?: 'off' | 'low' | 'high' | 'max'
1448
+ analysisReasoning?: 'off' | 'low' | 'high' | 'max'
1449
+ chapterChars?: number
1450
+ maxTokens?: number
1451
+ reviewPassScore?: number
1452
+ autoReview?: boolean
1453
+ autoAuthorReview?: boolean
1454
+ autoReviewAfterRevise?: boolean
1455
+ /** 自定义背景图(URL / dataURL / 服务端路径引用)。 */
1456
+ themeBackground?: string
1457
+ /** 自定义背景遮罩/模糊强度 0-80。 */
1458
+ themeBackgroundBlur?: number
1459
+ /** 玻璃透明度 0-100(100=当前原样)。 */
1460
+ themeOpacity?: number
1461
+ enableAdaptMode?: boolean
1462
+ /** 手动添加的模型库(完整替换保存)。 */
1463
+ savedModels?: SavedModel[]
1464
+ }
1465
+
1466
+ // ------------------------------------------------------------ assistant
1467
+
1468
+ /** One assistant conversation message (persisted per project). */
1469
+ export interface AssistantMessage {
1470
+ role: 'user' | 'assistant' | 'tool'
1471
+ /** Message text (tool messages carry the tool result). */
1472
+ content: string
1473
+ /** ISO timestamp. */
1474
+ ts: string
1475
+ /** For tool messages: which tool ran. */
1476
+ tool?: string
1477
+ }
1478
+
1479
+ /** POST /assistant request: one user turn. */
1480
+ export interface AssistantRequest {
1481
+ message: string
1482
+ }
1483
+
1484
+ /** One NDJSON frame of the assistant stream. */
1485
+ export type AssistantFrame =
1486
+ | { type: 'delta'; text: string }
1487
+ | { type: 'tool'; name: string; status: 'start' | 'done' | 'error'; detail?: string }
1488
+ /** Live output while a tool runs (e.g. chapter text being generated). */
1489
+ | { type: 'toolDelta'; name: string; text: string }
1490
+ /** 工具完整结果(供前端渲染成结构化卡片,如拆书/导演)。 */
1491
+ | { type: 'toolResult'; name: string; text: string }
1492
+ | { type: 'done' }
1493
+ | { type: 'error'; message: string }
1494
+
1495
+ /** GET /assistant-history response. */
1496
+ export interface AssistantHistoryResponse {
1497
+ messages: AssistantMessage[]
1498
+ }
1499
+
1500
+ // ---------------------------------------------------------- writing assets
1501
+
1502
+ /** 题材基底库:一本书属于哪个阅读市场。树形(题材→子题材→下级)。 */
1503
+ export interface GenreNode {
1504
+ /** 稳定标识(内置库交叉引用)。 */
1505
+ id?: string
1506
+ /** 题材名称(标签,如「仙侠修真」「都市异能」)。 */
1507
+ name: string
1508
+ /** 题材特征、常见爽点、叙事重心或读者期待。 */
1509
+ description: string
1510
+ /** 该题材的写法指引(开书定盘/卷计划用,区别于「读者期待」)。 */
1511
+ template?: string
1512
+ /** 子题材。 */
1513
+ children: GenreNode[]
1514
+ }
1515
+
1516
+ /** 推进模式库:读者为什么继续看下一章。 */
1517
+ export interface ProgressionMode {
1518
+ /** 稳定标识(与内置库交叉引用)。 */
1519
+ key?: string
1520
+ /** 模式名称(如「升级变强」「经营扩张」「解谜揭露」)。 */
1521
+ name: string
1522
+ /** 核心驱动力:靠什么制造追读动力。 */
1523
+ driver: string
1524
+ /** 读者期待:每隔几章获得什么变化或回报。 */
1525
+ readerExpectation: string
1526
+ /** 常见兑现方式(爽点如何落地)。 */
1527
+ payoffs: string[]
1528
+ /** 节奏风险:最怕什么(重复升级、冲突变弱、谜题拖太久…)。 */
1529
+ risks: string[]
1530
+ /** 主模式或辅助模式。 */
1531
+ primary: boolean
1532
+ /** 该模式的写法指引(开书定盘/卷计划用)。 */
1533
+ template?: string
1534
+ /** 推进单位序列(每章如何推进,如「立威→打破质疑→扩大影响→碾压」)。 */
1535
+ progressionUnits?: string[]
1536
+ /** 允许出现的冲突形态。 */
1537
+ allowedConflictForms?: string[]
1538
+ /** 应避免的冲突形态(跑偏信号)。 */
1539
+ forbiddenConflictForms?: string[]
1540
+ /** 冲突烈度上限(low/medium/high),用于卷/章计划和审稿对齐。 */
1541
+ conflictCeiling?: 'low' | 'medium' | 'high'
1542
+ /** 单章推进单位说明。 */
1543
+ chapterUnit?: string
1544
+ /** 卷末应兑现的回报。 */
1545
+ volumeReward?: string
1546
+ /** 主驱动必须持续出现的信号(读者期待确认)。 */
1547
+ mandatorySignals?: string[]
1548
+ /** 反信号:出现即跑偏。 */
1549
+ antiSignals?: string[]
1550
+ /** 优先用的问题解决方式。 */
1551
+ resolutionStyle?: string
1552
+ }
1553
+
1554
+ /** 反 AI 规则:一条「要避免的问题 + 修正方向」。 */
1555
+ export interface AntiAiRule {
1556
+ /** 规则名(如「禁止解释型心理描写」「AI 高频套话」)。 */
1557
+ name: string
1558
+ /** 稳定标识(与 defaultAntiAiRuleKeys 交叉引用;缺省用 name)。 */
1559
+ key?: string
1560
+ /** 要避免的表达问题,具体可检查。 */
1561
+ avoid: string
1562
+ /** 推荐修正方向。 */
1563
+ fix: string
1564
+ /** 命中即告警的具体表达模式(用于审稿逐条核对与去 AI 味检测)。 */
1565
+ detectPatterns?: string[]
1566
+ /** 是否内置全局规则(内置规则随插件发布,项目规则为用户自定义)。 */
1567
+ builtin?: boolean
1568
+ /** 规则类别:forbidden=禁止类(命中即问题)/ risk=风险类(需注意但不硬伤)/ encourage=鼓励类(不命中不算错,只作建议)。 */
1569
+ severity?: 'forbidden' | 'risk' | 'encourage'
1570
+ /** 问题严重度(用于审稿优先级;缺省按类别推断)。 */
1571
+ riskLevel?: 'low' | 'medium' | 'high'
1572
+ /** 生成时直接注入的约束指令(缺失时回退到 avoid)。 */
1573
+ promptInstruction?: string
1574
+ /** 是否允许自动改写(risk 类通常 false)。 */
1575
+ autoRewrite?: boolean
1576
+ /** 是否为全局基线规则(新书默认启用,防止规则丢失后降级)。 */
1577
+ globalBaselineEnabled?: boolean
1578
+ /** 是否启用(缺省 true)。 */
1579
+ enabled?: boolean
1580
+ /** 作用域(缺省 all)。 */
1581
+ scope?: Array<'writing' | 'review' | 'polish' | 'all'>
1582
+ }
1583
+
1584
+ /** 预置写法模板(来自 AI-Novel-Writing-Assistant 内置数据,一键绑定无需样本文本)。 */
1585
+ export interface StyleTemplateNarrativeRules {
1586
+ progressionMode?: string
1587
+ sceneUnitPattern?: string[]
1588
+ multiPov?: boolean
1589
+ looping?: boolean
1590
+ endingStyle?: string
1591
+ povSwitchStyle?: string
1592
+ summary?: string
1593
+ }
1594
+
1595
+ export interface StyleTemplateCharacterRules {
1596
+ allowSelfReflection?: boolean
1597
+ emotionExpression?: string
1598
+ defenseMechanisms?: string[]
1599
+ facePriority?: boolean
1600
+ dialogueStyle?: string
1601
+ summary?: string
1602
+ }
1603
+
1604
+ export interface StyleTemplateLanguageRules {
1605
+ register?: string
1606
+ roughness?: number
1607
+ allowIncompleteSentences?: boolean
1608
+ allowSwearing?: boolean
1609
+ sentenceVariation?: string
1610
+ allowUselessDetails?: boolean
1611
+ summary?: string
1612
+ }
1613
+
1614
+ export interface StyleTemplateRhythmRules {
1615
+ pace?: string
1616
+ paragraphDensity?: string
1617
+ allowFragmentedFlow?: boolean
1618
+ actionOverExplanation?: boolean
1619
+ summary?: string
1620
+ }
1621
+
1622
+ export interface StyleTemplate {
1623
+ /** 模板 key(如 power-up-escalation)。 */
1624
+ key: string
1625
+ /** 模板名(如「爽文递进推进流」)。 */
1626
+ name: string
1627
+ /** 模板说明。 */
1628
+ description: string
1629
+ /** 分类(如「爽文流」「悬疑流」)。 */
1630
+ category: string
1631
+ /** 适用题材。 */
1632
+ applicableGenres: string[]
1633
+ /** 标签(便于筛选)。 */
1634
+ tags?: string[]
1635
+ /** 一句话分析(模板定位说明)。 */
1636
+ analysisMarkdown?: string
1637
+ /** 叙述规则(结构化)。 */
1638
+ narrative?: StyleTemplateNarrativeRules
1639
+ /** 角色规则(结构化)。 */
1640
+ character?: StyleTemplateCharacterRules
1641
+ /** 语言规则(结构化)。 */
1642
+ language?: StyleTemplateLanguageRules
1643
+ /** 节奏规则(结构化)。 */
1644
+ rhythm?: StyleTemplateRhythmRules
1645
+ /** 叙述规则(扁平,兼容旧数据)。 */
1646
+ proseRules: string[]
1647
+ /** 角色/台词规则(扁平,兼容旧数据)。 */
1648
+ dialogueRules: string[]
1649
+ /** 语言规则(扁平,兼容旧数据)。 */
1650
+ languageRules: string[]
1651
+ /** 节奏规则(扁平,兼容旧数据)。 */
1652
+ rhythmRules: string[]
1653
+ /** 该模板默认绑定的反 AI 规则 key(内置规则名)。 */
1654
+ defaultAntiAiRuleKeys: string[]
1655
+ }
1656
+
1657
+ /** 起始风格画像:无样本文本也能快速绑定一套写法(对齐上游 DEFAULT_STARTER_STYLE_PROFILES)。 */
1658
+ export interface StarterStyleProfile {
1659
+ /** stable key(如 starter-power-up)。 */
1660
+ key: string
1661
+ /** 绑定到的写法模板 key。 */
1662
+ templateKey: string
1663
+ /** 画像名。 */
1664
+ name: string
1665
+ /** 画像说明。 */
1666
+ description: string
1667
+ }
1668
+
1669
+ /** 剧情桥段库:可复用的情节套路/桥段(作者阅读经验沉淀,与书内 Plotline 不同层)。 */
1670
+ export interface PlotBeatTemplate {
1671
+ /** 模板 key(如 face-slap / exit-wedding)。 */
1672
+ key: string
1673
+ /** 桥段名(如「打脸」「退婚」)。 */
1674
+ name: string
1675
+ /** 分类(如「装逼打脸」「身份逆袭」)。 */
1676
+ category: string
1677
+ /** 一句话说明。 */
1678
+ summary: string
1679
+ /** 适用位置(开局/前期/中期/后期/高潮/结尾)。 */
1680
+ position: string
1681
+ /** 前置条件。 */
1682
+ preconditions: string[]
1683
+ /** 爽点来源。 */
1684
+ payoffSource: string[]
1685
+ /** 常用组合(可搭配的桥段)。 */
1686
+ combos: string[]
1687
+ /** 禁忌(别用烂/别用死)。 */
1688
+ taboos: string[]
1689
+ /** 适用题材。 */
1690
+ applicableGenres: string[]
1691
+ }
1692
+
1693
+ /** 写法引擎:从样本文本提取的叙事风格资产。 */
1694
+ export interface StyleAsset {
1695
+ /** 资产名(如「林越式痞坏」「冷峻猎手风」)。 */
1696
+ name: string
1697
+ /** 叙述视角与句式节奏。 */
1698
+ proseRules: string[]
1699
+ /** 角色台词风格。 */
1700
+ dialogueRules: string[]
1701
+ /** 描写密度与情绪表达。 */
1702
+ descriptionRules: string[]
1703
+ /** 表达边界(不要做什么)。 */
1704
+ boundaries: string[]
1705
+ /** 来源样本文本(可空)。 */
1706
+ sourceText?: string
1707
+ /** 仿写预设:imitate=高保真仿写 / balanced=平衡 / transfer=迁移(去指纹)。 */
1708
+ preset?: 'imitate' | 'balanced' | 'transfer'
1709
+ /** 指纹风险:仿写时照搬原作独特表达的风险。 */
1710
+ fingerprintRisk?: 'low' | 'medium' | 'high'
1711
+ /** 净化后的写作指引(可安全用于生成,去掉了会暴露来源的具体细节)。 */
1712
+ writingGuidance?: string[]
1713
+ /** 禁止照搬的原作特有实体(人名/地名/核心设定句式),生成时需避开。 */
1714
+ forbiddenEntities?: string[]
1715
+ /** 创建时间。 */
1716
+ createdAt: string
1717
+ }
1718
+
1719
+ /** 写作公式(从样本文本分层提取的"这套文怎么写"浓缩,供生成/改写复用)。 */
1720
+ export interface StyleFormula {
1721
+ /** 稳定 key。 */
1722
+ key: string
1723
+ /** 公式名。 */
1724
+ name: string
1725
+ /** 提取深度:basic=骨架 / standard=完整 / deep=逐句细化。 */
1726
+ depth: 'basic' | 'standard' | 'deep'
1727
+ /** 重点聚焦域(如 开场/对话/节奏/爽点密度)。 */
1728
+ focusAreas: string[]
1729
+ /** 公式正文(Markdown)。 */
1730
+ formula: string
1731
+ /** 应用指引(生成/改写时如何套用)。 */
1732
+ applyGuidance: string
1733
+ /** 创建时间。 */
1734
+ createdAt: string
1735
+ }
1736
+
1737
+ /** 项目写作资产(题材基底 + 推进模式 + 反 AI 规则 + 写法资产)。 */
1738
+ export interface ProjectAssets {
1739
+ /** 本书选用的题材(可以是题材基底库中某节点名)。 */
1740
+ genre?: GenreNode
1741
+ /** 主推进模式。 */
1742
+ primaryProgression?: ProgressionMode
1743
+ /** 辅助推进模式。 */
1744
+ auxiliaryProgressions: ProgressionMode[]
1745
+ /** 生效的反 AI 规则(内置 + 自定义)。 */
1746
+ antiAiRules: AntiAiRule[]
1747
+ /** 绑定的写法资产。 */
1748
+ styleAssets: StyleAsset[]
1749
+ /** 写作公式(分层提取:basic/standard/deep)。 */
1750
+ styleFormulas?: StyleFormula[]
1751
+ /** 资产更新时间。 */
1752
+ updatedAt?: string
1753
+ }
1754
+
1755
+ /** GET /assets response(含全局题材库与反 AI 规则库)。 */
1756
+ export interface AssetsResponse {
1757
+ projectAssets: ProjectAssets
1758
+ /** 全局题材基底库(可复用资产,跨书)。 */
1759
+ genreLibrary: GenreNode[]
1760
+ /** 全局反 AI 规则库(内置默认规则)。 */
1761
+ antiAiLibrary: AntiAiRule[]
1762
+ /** 预置写法模板(一键绑定,无需样本文本)。 */
1763
+ styleTemplates: StyleTemplate[]
1764
+ /** 内置推进模式候选。 */
1765
+ progressionLibrary: ProgressionMode[]
1766
+ /** 起始风格画像(无样本文本快速绑定写法)。 */
1767
+ starterStyleProfiles: StarterStyleProfile[]
1768
+ /** 内置剧情桥段库(可复用套路)。 */
1769
+ plotBeatLibrary: PlotBeatTemplate[]
1770
+ }
1771
+
1772
+ /** POST /assets request:更新项目写作资产(部分字段可选)。 */
1773
+ export interface AssetsPatch {
1774
+ genre?: GenreNode
1775
+ primaryProgression?: ProgressionMode
1776
+ auxiliaryProgressions?: ProgressionMode[]
1777
+ antiAiRules?: AntiAiRule[]
1778
+ styleAssets?: StyleAsset[]
1779
+ styleFormulas?: StyleFormula[]
1780
+ }
1781
+
1782
+ /** POST /style-engine request:从样本文本提取写法资产。 */
1783
+ export interface StyleEngineRequest {
1784
+ /** 样本文本(风格来源)。 */
1785
+ sampleText: string
1786
+ /** 资产名(可选,默认「风格资产 N」)。 */
1787
+ name?: string
1788
+ }
1789
+
1790
+ // ---------------------------------------------------------- author assets (总数据)
1791
+
1792
+ /** 作者资产库中一条可跨书复用的资产(笔法/红线/套路/角色模板/世界观模板等)。 */
1793
+ export interface AuthorStyleAsset {
1794
+ /** 稳定 id(本地唯一)。 */
1795
+ id: string
1796
+ /** 资产名(如「短句快节奏爽文风」「林越式痞坏角色」)。 */
1797
+ name: string
1798
+ /** 资产类型。 */
1799
+ kind: 'style' | 'antiAi' | 'progression' | 'genre' | 'roleTemplate' | 'worldTemplate' | 'plotBeat' | 'custom'
1800
+ /** 一句话摘要。 */
1801
+ summary: string
1802
+ /** 资产正文内容(按 kind 约定解读的文本/JSON 描述)。 */
1803
+ content: string
1804
+ /** 结构化载荷(角色模板/世界观模板等可结构化字段;缺省为 null)。 */
1805
+ structured?: Record<string, unknown>
1806
+ /** 来源书名(哪本书提炼/收藏而来)。 */
1807
+ sourceBooks: string[]
1808
+ /** 标签。 */
1809
+ tags: string[]
1810
+ /** 来源样本文本(可选)。 */
1811
+ sourceText?: string
1812
+ /** 创建时间。 */
1813
+ createdAt: string
1814
+ /** 更新时间。 */
1815
+ updatedAt: string
1816
+ }
1817
+
1818
+ /** 作者资产库(跨书总数据):按作者维度聚合的可复用资产。 */
1819
+ export interface AuthorAssetLibrary {
1820
+ /** 货架版本,便于未来迁移。 */
1821
+ version: 1
1822
+ items: AuthorStyleAsset[]
1823
+ }
1824
+
1825
+ /** GET /author-assets 响应。 */
1826
+ export interface AuthorAssetsResponse {
1827
+ assets: AuthorAssetLibrary
1828
+ }
1829
+
1830
+ /** POST /author-assets/upsert 请求:新增或按 id 更新一条资产。 */
1831
+ export interface AuthorAssetUpsertRequest {
1832
+ asset: AuthorStyleAsset
1833
+ }
1834
+
1835
+ /** POST /author-assets/remove 请求:删除一条资产。 */
1836
+ export interface AuthorAssetRemoveRequest {
1837
+ id: string
1838
+ }
1839
+
1840
+ // ---------------------------------------------------------- adaptation (改编模式)
1841
+
1842
+ /** 改编可改范围的单个维度(矩阵的一行)。 */
1843
+ export interface AdaptationDimension {
1844
+ /** 维度 key(如 realm/name/goldenFinger…)。 */
1845
+ key: string
1846
+ /** 维度名(如「大世界」「修为体系」「主角名」「金手指」)。 */
1847
+ title: string
1848
+ /** 可改度:保留 / 可改影响大 / 可改影响小 / 可自由改 / 仅视觉包装。 */
1849
+ mutability: 'locked' | 'big' | 'small' | 'free' | 'visual'
1850
+ /** 原文当前值(从正文提炼,附证据)。 */
1851
+ current: string
1852
+ /** 该值在正文中的出现证据(章节/频次,可空)。 */
1853
+ evidence?: string
1854
+ /** 建议的候选新值(可空,每套含名称与一句话说明)。 */
1855
+ candidates?: Array<{ name: string; desc?: string }>
1856
+ /** 联动影响说明(改了会影响哪些章节/角色/伏笔/术语)。 */
1857
+ impact: string
1858
+ /** 风险评级。 */
1859
+ risk: 'high' | 'medium' | 'low'
1860
+ }
1861
+
1862
+ /** POST /adapt/analyze 请求:上传全文做改编分析。 */
1863
+ export interface AdaptAnalyzeRequest {
1864
+ /** 全文文本(优先)。 */
1865
+ text: string
1866
+ /** 或服务器端全文文件路径。 */
1867
+ filePath?: string
1868
+ }
1869
+
1870
+ /** POST /adapt/analyze 响应。 */
1871
+ export interface AdaptAnalyzeResponse {
1872
+ /** 识别书名(文件名推断或正文首行)。 */
1873
+ bookName: string
1874
+ /** 拆出的章节数。 */
1875
+ chapters: number
1876
+ /** 反推的初始大纲(可空)。 */
1877
+ outline?: string
1878
+ /** 可改范围矩阵。 */
1879
+ dimensions: AdaptationDimension[]
1880
+ /** 分析消耗说明。 */
1881
+ note?: string
1882
+ }
1883
+
1884
+ /** 一条改编映射(原值 → 新值)。 */
1885
+ export interface AdaptationMapping {
1886
+ /** 原值(如「林尘」「练气」「青云宗」)。 */
1887
+ source: string
1888
+ /** 新值(如「楚风」「凝元」「天渊阁」)。 */
1889
+ target: string
1890
+ /** 适用范围。 */
1891
+ scope: 'name' | 'realm' | 'faction' | 'term' | 'other'
1892
+ /** 说明(可空)。 */
1893
+ note?: string
1894
+ }
1895
+
1896
+ /** 改编规则:哪些必须保留、哪些允许改、一致性约束。 */
1897
+ export interface AdaptationRules {
1898
+ /** 必须保留的要素(骨架/人物动机/伏笔逻辑/爽点结构…)。 */
1899
+ preserve: string[]
1900
+ /** 允许改变的要素。 */
1901
+ change: string[]
1902
+ /** 改编红线/一致性要求。 */
1903
+ constraints: string[]
1904
+ }
1905
+
1906
+ /** 一组改编方案(映射表 + 规则 + 联动影响清单)。 */
1907
+ export interface AdaptationProposal {
1908
+ /** 映射表(原→新)。 */
1909
+ mappings: AdaptationMapping[]
1910
+ /** 改编规则。 */
1911
+ rules: AdaptationRules
1912
+ /** 联动影响清单。 */
1913
+ impacts: Array<{ item: string; detail: string; risk: 'high' | 'medium' | 'low'; chapters?: number[] }>
1914
+ }
1915
+
1916
+ /** POST /adapt/propose 请求:由用户勾选的维度 + 新值生成改编方案。 */
1917
+ export interface AdaptProposeRequest {
1918
+ /** 原文全文(复用,便于 LLM 核对联动影响)。 */
1919
+ text: string
1920
+ /** 用户确认要改的维度(含原值与新值)。 */
1921
+ selections: Array<{ key: string; title: string; current: string; target: string; mutability: string }>
1922
+ /** 若已分析过,可携带完整矩阵作为上下文。 */
1923
+ dimensions?: AdaptationDimension[]
1924
+ }
1925
+
1926
+ /** POST /adapt/propose 响应。 */
1927
+ export interface AdaptProposeResponse {
1928
+ proposal: AdaptationProposal
1929
+ }
1930
+
1931
+ /** POST /adapt/execute 请求:执行改编(replace=术语替换;rewrite=逐章 LLM 重写)。 */
1932
+ export interface AdaptExecuteRequest {
1933
+ /** 原文全文。 */
1934
+ text: string
1935
+ /** 改编映射表。 */
1936
+ mappings: AdaptationMapping[]
1937
+ /** 改编规则(rewrite 模式生效:保留/允许变/红线)。 */
1938
+ rules?: AdaptationRules
1939
+ /** 执行模式:replace(术语替换)或 rewrite(逐章重写)。 */
1940
+ mode?: 'replace' | 'rewrite'
1941
+ /** rewrite 模式:只重写前 N 章(0/缺省 = 全部,且在 startNo/endNo 窗口内)。 */
1942
+ maxChapters?: number
1943
+ /** rewrite 模式:起始章号(含,默认 1)。 */
1944
+ startNo?: number
1945
+ /** rewrite 模式:结束章号(含;0/缺省 = 到全书末尾)。 */
1946
+ endNo?: number
1947
+ }
1948
+
1949
+ /** POST /adapt/execute 响应。 */
1950
+ export interface AdaptExecuteResponse {
1951
+ /** 改编后的全文。 */
1952
+ adaptedText: string
1953
+ /** 执行的映射数。 */
1954
+ mappings: number
1955
+ /** 命中统计:每条映射的替换次数。 */
1956
+ hits: Array<{ source: string; target: string; count: number }>
1957
+ /** 执行模式(replace / rewrite)。 */
1958
+ mode?: 'replace' | 'rewrite'
1959
+ /** rewrite 模式的逐章结果(no/title/chars)。 */
1960
+ rewritten?: Array<{ no: number; title: string; chars: number }>
1961
+ /** rewrite 模式下重写失败、保留原章的章节号。 */
1962
+ skipped?: number[]
1963
+ }
1964
+
1965
+ /** POST /adapt/rewrite-stream 的 NDJSON 帧(逐章进度 + 结束结果)。 */
1966
+ export type AdaptRewriteFrame =
1967
+ | { type: 'progress'; completed: number; total: number; no: number; title: string }
1968
+ | { type: 'done'; result: AdaptExecuteResponse }
1969
+ | { type: 'error'; message: string }
1970
+
1971
+ /** POST /adapt/save 请求:保存改编全文为新书(原书保留,登记书架)。 */
1972
+ export interface AdaptSaveRequest {
1973
+ /** 改编后的全文。 */
1974
+ text: string
1975
+ /** 新书名(缺省为「改编新书」;建议用「<原著>·改编版」)。 */
1976
+ bookName?: string
1977
+ /** 新书输出目录(缺省 ~/.dsh/novels/书名)。 */
1978
+ outputDir?: string
1979
+ /** 可附带反推大纲(写进新项目,便于后续续写/编辑)。 */
1980
+ outline?: string
1981
+ }
1982
+
1983
+ /** POST /adapt/save 响应。 */
1984
+ export interface AdaptSaveResponse {
1985
+ /** 登记后的书架条目。 */
1986
+ book: BookEntry
1987
+ /** 新书名。 */
1988
+ bookName: string
1989
+ /** 成功拆出的章节数。 */
1990
+ chapters: number
1991
+ /** 因内容过短被跳过的章节标题列表。 */
1992
+ skipped: string[]
1993
+ /** 新书输出目录。 */
1994
+ outputDir: string
1995
+ }
1996
+
1997
+ /** POST /adapt/materialize 请求:从源全文 + 用户编辑后的改编方案,提炼新书资料并保存为「待写新书」。 */
1998
+ export interface AdaptMaterializeRequest {
1999
+ /** 源书全文。 */
2000
+ text: string
2001
+ /** 新书名(缺省为「<源书名>·改编版」)。 */
2002
+ bookName?: string
2003
+ /** 新书输出目录(缺省 ~/.dsh/novels/书名)。 */
2004
+ outputDir?: string
2005
+ /** 反推大纲(来自分析;缺少时用源文章题兜底)。 */
2006
+ outline?: string
2007
+ /** 用户编辑后的改编方案(映射表 + 规则)。 */
2008
+ proposal: AdaptationProposal
2009
+ /** 拟规划章节数(缺省 30,可在前端调整)。 */
2010
+ chapterCount?: number
2011
+ }
2012
+
2013
+ /** POST /adapt/materialize 响应:提炼后的新书资料(预览,尚未落盘;保存走 /adapt/materialize-save)。 */
2014
+ export interface AdaptMaterializeResponse {
2015
+ /** 书架条目(仅在已保存时存在;预览阶段为 undefined)。 */
2016
+ book?: BookEntry
2017
+ /** 新书名。 */
2018
+ bookName: string
2019
+ /** 改编后总纲。 */
2020
+ outline: string
2021
+ /** 改编后道藏。 */
2022
+ bible: StoryBible
2023
+ /** 改编后角色库。 */
2024
+ roles: RoleRecord[]
2025
+ /** 改编后大世界。 */
2026
+ world: WorldState
2027
+ /** 改编后卷计划。 */
2028
+ volumes: Volume[]
2029
+ /** 改编后章节计划(status=pending)。 */
2030
+ chapters: ChapterPlan[]
2031
+ /** 新书输出目录。 */
2032
+ outputDir: string
2033
+ }
2034
+
2035
+ /** POST /adapt/materialize-save 请求:把预览/微调后的新书资料写入并登记书架。 */
2036
+ export interface AdaptMaterializeSaveRequest {
2037
+ /** 新书名(缺省为「改编版」)。 */
2038
+ bookName?: string
2039
+ /** 新书输出目录(缺省 ~/.dsh/novels/书名)。 */
2040
+ outputDir?: string
2041
+ /** 改编后总纲。 */
2042
+ outline: string
2043
+ /** 改编后道藏。 */
2044
+ bible: StoryBible
2045
+ /** 改编后角色库。 */
2046
+ roles: RoleRecord[]
2047
+ /** 改编后大世界。 */
2048
+ world: WorldState
2049
+ /** 改编后卷计划。 */
2050
+ volumes: Volume[]
2051
+ /** 改编后章节计划(status=pending)。 */
2052
+ chapters: ChapterPlan[]
2053
+ }
2054
+
2055
+ /** POST /adapt/materialize-save 响应。 */
2056
+ export interface AdaptMaterializeSaveResponse {
2057
+ /** 登记后的书架条目。 */
2058
+ book: BookEntry
2059
+ /** 新书名。 */
2060
+ bookName: string
2061
+ /** 成功写入的章节数。 */
2062
+ chapters: number
2063
+ /** 新书输出目录。 */
2064
+ outputDir: string
2065
+ }
2066
+
2067
+ /** POST /plugin/update 响应:插件自更新结果。 */
2068
+ export interface PluginUpdateResponse {
2069
+ ok: boolean
2070
+ /** 更新结果说明(成功/失败/环境提示)。 */
2071
+ message: string
2072
+ }