@waterwx/dsh-novel-forge 1.3.3 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/protocol.ts CHANGED
@@ -1,1207 +1,1277 @@
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
- scenes: '/api/dsh-novel-forge/scenes',
62
- visualRules: '/api/dsh-novel-forge/visual-rules',
63
- /** 作者复盘补跑:对已写章节补齐 authorReview(全书流式 / 单章 JSON)。 */
64
- reviewBackfill: '/api/dsh-novel-forge/review/backfill',
65
- /** 章节复位:generating 卡死 → pending(可重新生成)。 */
66
- chapterReset: '/api/dsh-novel-forge/chapter/reset',
67
- /** 章节直接通过:作者对 rejected/written 章节行使最终决定权。 */
68
- chapterApprove: '/api/dsh-novel-forge/chapter/approve',
69
- /** 敏感词检查:全书已写章节或指定文本。 */
70
- sensitiveCheck: '/api/dsh-novel-forge/sensitive-check',
71
- /** 开书想法 → AI 补全大纲:输入一句话想法,生成 2-3 个可选大纲方案。 */
72
- outlineSuggest: '/api/dsh-novel-forge/outline/suggest',
73
- /** 拆书分析:对已写章节做结构/人物/文风/卖点四维体检(两阶段:源笔记→分节分析)。 */
74
- breakdown: '/api/dsh-novel-forge/breakdown',
75
- /** 漫剧分镜生成:章节 → 角色锚点 + 分镜表(可适配豆包/Seedance/SD)。 */
76
- /** 漫剧分集计划:读一卷 → 按故事弧线分集(高潮拆集/过渡并章)。 */
77
- /** 漫画脚本:章节 → 分页分格漫画脚本(含角色视觉锚点)。 */
78
- /** 生产单:启动批量生产(计划补足 + 逐章生成 + 被拒分级处理)。 */
79
- runStart: '/api/dsh-novel-forge/run/start',
80
- /** 生产单控制:pause / resume / stop。 */
81
- runControl: '/api/dsh-novel-forge/run/control',
82
- /** 生产单状态(含进度统计与日志)。 */
83
- runStatus: '/api/dsh-novel-forge/run/status',
84
- config: '/api/dsh-novel-forge/config',
85
- openFolder: '/api/dsh-novel-forge/open-folder',
86
- } as const
87
-
88
- /** 书架:一本书的条目。 */
89
- export interface BookEntry {
90
- /** 稳定 id。 */
91
- id: string
92
- /** 书名。 */
93
- bookName: string
94
- /** 该书输出目录(独立项目目录)。 */
95
- outputDir: string
96
- /** 创建时间。 */
97
- createdAt: string
98
- /** 最后活动时间。 */
99
- updatedAt: string
100
- }
101
-
102
- /** 书架快照(含每本书的进度摘要)。 */
103
- export interface BookshelfSnapshot {
104
- books: Array<BookEntry & { done: number; total: number; hasProject: boolean; hasCover: boolean; blurb?: string }>
105
- /** 当前激活的书 id(无则 null)。 */
106
- activeBookId: string | null
107
- }
108
-
109
- /** POST /bookshelf 请求:创建新书。 */
110
- export interface BookCreateRequest {
111
- bookName: string
112
- outputDir?: string
113
- /** 开书向导:创建时直接导入的大纲文本(提供则立即建立项目)。 */
114
- outline?: string
115
- }
116
-
117
- /** POST /reset 请求:重置项目(可选更新大纲)。 */
118
- export interface ResetRequest {
119
- /** 新大纲文本;提供则替换 outline,否则保留原大纲。 */
120
- outline?: string
121
- }
122
-
123
- /** POST /bookshelf/activate 请求:切换当前书。 */
124
- export interface BookActivateRequest {
125
- id: string
126
- }
127
-
128
- /** POST /bookshelf/remove 请求:移除书架条目。 */
129
- export interface BookRemoveRequest {
130
- id: string
131
- }
132
-
133
- /** Chapter lifecycle states (the writing pipeline's state machine). */
134
- export type ChapterStatus =
135
- | 'pending' // planned, not started
136
- | 'generating' // LLM writing right now
137
- | 'written' // body on disk, awaiting review
138
- | 'reviewing' // review in progress
139
- | 'approved' // passed review (or user-approved)
140
- | 'rejected' // review found problems
141
- | 'error' // generation failed
142
-
143
- /** One chapter in the plan. */
144
- export interface ChapterPlan {
145
- /** 1-based chapter number (stable identity; files are named from it). */
146
- no: number
147
- /** Volume this chapter belongs to (1-based; 0 = unassigned). */
148
- volume: number
149
- /** Chapter title, decided by the LLM plan step. */
150
- title: string
151
- /** Story beats / plot points for this chapter (model-facing guidance). */
152
- beats: string
153
- /** Target character count (defaults to the configured chapter size). */
154
- targetChars: number
155
- /** Generation/review state. */
156
- status: ChapterStatus
157
- /** 进入 generating 的时间(用于超时自动复位;未在生成时无此字段)。 */
158
- generatingAt?: string
159
- /** Actual character count once generated. */
160
- chars?: number
161
- /** Failure message when status is 'error'. */
162
- error?: string
163
- /** Output file name once generated (relative to the output dir). */
164
- file?: string
165
- /** LLM summary of the chapter (narrative memory for later chapters). */
166
- summary?: string
167
- /** Latest review report (present once reviewed). */
168
- review?: ReviewReport
169
- /** 作者复盘:钩子兑现/结尾钩子/剧情线推进/连续性/节奏趋势(生成后自动)。 */
170
- authorReview?: AuthorReview
171
- /**
172
- * 待确认草稿:润色(去AI味)或整章重写的产物正文。生成时先存这里,
173
- * 用户看过对比后点「采纳」才覆盖正文文件;点「放弃」则丢弃。刷新页面不丢失。
174
- */
175
- pendingDraft?: string
176
- }
177
-
178
- /** 作者复盘:叙事结构层面的逐章检查(钩子/推进/连续性/趋势)。 */
179
- export interface AuthorReview {
180
- /** 上一章结尾钩子是否在本章兑现。 */
181
- hookHonored: boolean
182
- /** 钩子兑现说明(未兑现时给出建议)。 */
183
- hookNote: string
184
- /** 本章结尾钩子强度 0-10。 */
185
- endingHook: number
186
- /** 剧情线推进情况(推进了哪条线/或未推进)。 */
187
- plotlineProgress: string
188
- /** 结构化:本章推进的剧情线名称列表(与项目剧情线 name 精确匹配,复盘后自动关联章节)。 */
189
- advancedLines?: string[]
190
- /** 连续性检查(人物位置/时间/伤势/资源是否与上章衔接)。 */
191
- continuity: string
192
- /** 近期节奏趋势提示(拖沓/爽点密度等)。 */
193
- trend: string
194
- /** 复盘时间。 */
195
- reviewedAt: string
196
- }
197
-
198
- /** One review finding. */
199
- export interface ReviewIssue {
200
- /** Severity: high = must fix, medium = should fix, low = suggestion. */
201
- severity: 'high' | 'medium' | 'low'
202
- /** What the problem is. */
203
- item: string
204
- /** Concrete suggestion for fixing it. */
205
- suggestion: string
206
- }
207
-
208
- /** AI review report for one chapter. */
209
- export interface ReviewReport {
210
- /** Overall score 0-100. */
211
- score: number
212
- /** Pass threshold (config; 70 default). */
213
- passed: boolean
214
- /** One-line verdict. */
215
- verdict: string
216
- /** Individual findings. */
217
- issues: ReviewIssue[]
218
- /** When the review ran. */
219
- reviewedAt: string
220
- }
221
-
222
- /** A volume of the book. */
223
- export interface Volume {
224
- /** 1-based volume number. */
225
- no: number
226
- /** Volume title. */
227
- title: string
228
- /** Volume positioning / summary. */
229
- summary: string
230
- /** First chapter number of this volume. */
231
- chapterStart: number
232
- /** Last chapter number (inclusive). */
233
- chapterEnd: number
234
- }
235
-
236
- /** A character card from the story bible. */
237
- export interface CharacterCard {
238
- name: string
239
- role: 'protagonist' | 'supporting' | 'antagonist' | 'other'
240
- /** Personality / traits (short lines). */
241
- traits: string[]
242
- /** Goals and motivations. */
243
- goals: string
244
- /** Key relations to other characters. */
245
- relations: string
246
- /** 知情度:该角色已经知道的事实/秘密(未列出的信息该角色不知道)。 */
247
- knowledge?: string[]
248
- }
249
-
250
- /** The structured story bible (worldbuilding extracted from the outline). */
251
- export interface StoryBible {
252
- /** Genre + tone tags. */
253
- genre: string
254
- /** Worldbuilding rules (power system, geography, factions...). */
255
- worldRules: string[]
256
- /** Character cards. */
257
- characters: CharacterCard[]
258
- /** Writing red lines (forbidden content / must-avoid tropes). */
259
- redLines: string[]
260
- /** Style guidance (pacing, pov, tone). */
261
- style: string[]
262
- /** When the bible was generated. */
263
- generatedAt?: string
264
- }
265
-
266
- /** A planted/active/resolved foreshadowing thread. */
267
- export interface Foreshadow {
268
- /** Stable id. */
269
- id: string
270
- /** What the foreshadow is. */
271
- description: string
272
- /** Chapter where it was planted (undefined = planned). */
273
- plantedChapter?: number
274
- /** Chapter where it should be paid off. */
275
- targetChapter?: number
276
- /** Lifecycle state. */
277
- status: 'planned' | 'planted' | 'progressing' | 'resolved' | 'abandoned'
278
- /** Resolution note when resolved. */
279
- resolvedNote?: string
280
- }
281
-
282
- /** 一条已确立的叙事事实(事实库/时间线,注入后续章节生成)。 */
283
- export interface ChapterFact {
284
- /** 来源章节号。 */
285
- chapterNo: number
286
- /** 事实文本(人物状态/境界资源/关系变化/伏笔落地等)。 */
287
- text: string
288
- }
289
-
290
- /** 一条全书质检发现的问题(一致性矛盾,定位到章)。 */
291
- export interface AuditIssue {
292
- /** 问题所在章节号(无法定位时 0)。 */
293
- chapterNo: number
294
- severity: 'high' | 'medium' | 'low'
295
- /** 矛盾描述。 */
296
- item: string
297
- /** 修改建议。 */
298
- suggestion: string
299
- }
300
-
301
- /** POST /audit 响应。 */
302
- export interface AuditResponse {
303
- issues: AuditIssue[]
304
- /** 参与质检的章节数。 */
305
- auditedChapters: number
306
- /** 质检时间。 */
307
- auditedAt: string
308
- }
309
-
310
- /** 全书质检的实时状态(通过 /status 暴露给面板/外部读取)。 */
311
- export interface AuditStatus {
312
- status: 'idle' | 'running' | 'done' | 'error'
313
- /** 开始时间(ISO)。 */
314
- startedAt?: string
315
- /** 结束时间(ISO)。 */
316
- finishedAt?: string
317
- /** 总批次数(0 = 尚未开始/无章节)。 */
318
- totalBatches: number
319
- /** 已完成批次数。 */
320
- completedBatches: number
321
- /** 参与质检的章节数。 */
322
- auditedChapters?: number
323
- /** 发现的问题数(done 后有效)。 */
324
- issuesCount?: number
325
- /** 最近一次质检的问题清单(done 后有效;error 时为空)。 */
326
- issues?: AuditIssue[]
327
- /** 失败信息(error 时有效)。 */
328
- error?: string
329
- }
330
-
331
- /** 一条剧情线(主线/支线/人物线/悬念线)。 */
332
- export interface Plotline {
333
- /** 稳定 id。 */
334
- id: string
335
- /** 线名。 */
336
- name: string
337
- /** 类型:主线 / 支线 / 人物线 / 悬念线。 */
338
- kind: 'main' | 'branch' | 'character' | 'mystery'
339
- /** 目标/终点(这条线最终要完成什么)。 */
340
- goal: string
341
- /** 当前进度说明(最近推进到哪)。 */
342
- progress: string
343
- /** 生命周期状态。 */
344
- status: 'active' | 'paused' | 'resolved' | 'abandoned'
345
- /** 关联章节号(推进/落地的章节)。 */
346
- chapters: number[]
347
- /** 创建时间。 */
348
- createdAt: string
349
- }
350
-
351
- /** POST /plotlines 请求:剧情线增删改 + 关联章节 + AI 辅助。 */
352
- export interface PlotlinesRequest {
353
- op: 'add' | 'update' | 'remove' | 'link' | 'suggest' | 'refresh' | 'health' | 'plan'
354
- /** add / update 时传入的完整剧情线。 */
355
- line?: Plotline
356
- /** remove / link / refresh 时的目标线 id。 */
357
- id?: string
358
- /** link 时关联的章节号。 */
359
- chapterNo?: number
360
- }
361
-
362
- /** 剧情线健康检查报告。 */
363
- export interface PlotlineHealthReport {
364
- /** 是否需要新线(需要 / 暂不需要 / 再写 X 章后需要)。 */
365
- verdict: string
366
- /** 建议添加新线的时机说明。 */
367
- timing: string
368
- /** 依据(基于数据的理由,每条一句)。 */
369
- reasons: string[]
370
- /** 各线健康度。 */
371
- lines: Array<{
372
- name: string
373
- /** ok=健康 / warning=预警 / stale=搁置过久。 */
374
- health: 'ok' | 'warning' | 'stale'
375
- note: string
376
- }>
377
- }
378
-
379
- /** AI 剧情方案:下一阶段目标 + 建议新线。 */
380
- export interface PlotlinePlan {
381
- /** 下一阶段(未来 5-10 章)剧情方向。 */
382
- direction: string
383
- /** 建议的新线(可逐条采纳)。 */
384
- suggestions: Plotline[]
385
- }
386
-
387
- /** POST /plotlines 响应。 */
388
- export interface PlotlinesResponse {
389
- plotlines: Plotline[]
390
- /** op=suggest 时的 AI 建议候选线。 */
391
- suggestions?: Plotline[]
392
- /** op=health 时的健康检查报告。 */
393
- health?: PlotlineHealthReport
394
- /** op=plan 时的剧情方案。 */
395
- plan?: PlotlinePlan
396
- }
397
-
398
- /** 一条敏感词命中。 */
399
- export interface SensitiveHit {
400
- /** 命中章节号(文本检测时为 0)。 */
401
- chapterNo: number
402
- /** 命中的违禁词。 */
403
- word: string
404
- /** 类别:政治 / 擦边 / 暴力 / 辱骂 / 广告 / 其他。 */
405
- category: string
406
- /** 出现次数。 */
407
- count: number
408
- }
409
-
410
- /** POST /sensitive-check 请求:检测指定章节/任意文本/全书。 */
411
- export interface SensitiveCheckRequest {
412
- /** 检测该章正文。 */
413
- chapterNo?: number
414
- /** 检测任意文本(优先于 chapterNo)。 */
415
- text?: string
416
- /** 扫描全部已写章节。 */
417
- all?: boolean
418
- }
419
-
420
- /** POST /sensitive-check 响应。 */
421
- export interface SensitiveCheckResponse {
422
- hits: SensitiveHit[]
423
- /** 参与扫描的章节数。 */
424
- scannedChapters: number
425
- }
426
-
427
- /** 开书想法 → AI 大纲方案(一个候选)。 */
428
- export interface OutlineCandidate {
429
- /** 唯一 id(前端暂留/换批用)。 */
430
- id: string
431
- /** 推荐书名。 */
432
- bookName: string
433
- /** 题材(如 仙侠修真 / 都市)。 */
434
- genre: string
435
- /** 核心卖点一句话。 */
436
- sellingPoint: string
437
- /** 完整大纲文本(可直接用作项目大纲,≥800 字)。 */
438
- outline: string
439
- }
440
-
441
- /** POST /outline/suggest 请求:想法 → 2-3 个可选大纲。 */
442
- export interface OutlineSuggestRequest {
443
- /** 作者想法(一两句话,≥50 字)。 */
444
- idea: string
445
- /** 本次要生成的候选数(默认 3,最多 3)。 */
446
- count?: number
447
- /** 已暂留方案的剧情方向摘要(换批时让 LLM 避开,防止与已留方案重复)。 */
448
- exclude?: string[]
449
- }
450
-
451
- /** POST /outline/suggest 响应。 */
452
- export interface OutlineSuggestResponse {
453
- candidates: OutlineCandidate[]
454
- }
455
-
456
- /** 拆书分析:一个分析小节。 */
457
- export interface BreakdownSection {
458
- /** 小节键:overview / plot / character / style / market。 */
459
- key: string
460
- /** 小节标题(如「拆书总览」)。 */
461
- title: string
462
- /** 可读分析稿(markdown)。 */
463
- markdown: string
464
- /** 结构化数据(程序可消费)。 */
465
- structured: Record<string, unknown>
466
- }
467
-
468
- /** 拆书分析:一条证据(结论→原文回溯)。 */
469
- export interface BreakdownEvidence {
470
- label: string
471
- excerpt: string
472
- /** 来源章节号(0 = 未定位)。 */
473
- chapterNo: number
474
- /** 指向的结构化字段。 */
475
- fieldKey?: string
476
- }
477
-
478
- /** POST /breakdown 请求:对已写章节做拆书分析。 */
479
- export interface BreakdownRequest {
480
- /** 分析范围:'recent'=最近 20 章 / 'volume:N'=第 N 卷 / 'all'=全书(默认 recent)。 */
481
- scope?: string
482
- /** 分析档位:'quick'=4 维(总览/剧情/人物/文风)/ 'standard'=5 维(+卖点)。 */
483
- preset?: 'quick' | 'standard'
484
- /** token 预算上限(默认 50000)。 */
485
- budgetTokens?: number
486
- }
487
-
488
- /** POST /breakdown 响应。 */
489
- export interface BreakdownResponse {
490
- sections: BreakdownSection[]
491
- evidence: BreakdownEvidence[]
492
- /** 参与分析的章节数。 */
493
- chaptersScanned: number
494
- /** 估算消耗 token。 */
495
- usedTokens: number
496
- }
497
-
498
- /** 角色卡:角色当前状态(从事实库聚合)。 */
499
- export interface RoleStatusCard {
500
- name: string
501
- /** protagonist / supporting / antagonist / other。 */
502
- role: string
503
- /** 当前状态一句话(境界/资源/伤势/心境)。 */
504
- status: string
505
- /** 最近出场章节。 */
506
- lastChapter: number
507
- /** 出场次数。 */
508
- appearances: number
509
- }
510
-
511
- /** 角色库条目(主表:作者维护 + AI 提炼 + 编年录自动聚合)。 */
512
- export interface RoleRecord {
513
- /** 角色名(唯一键)。 */
514
- name: string
515
- /** 定位:主角 / 女主 / 女配 / 配角 / 反派 / 路人。 */
516
- roleLabel: 'protagonist' | 'female_lead' | 'female_support' | 'support' | 'antagonist' | 'extra'
517
- /** 身份一句话(如:祭族后裔、青云宗杂役)。 */
518
- identity: string
519
- /** 性格标签。 */
520
- traits: string[]
521
- /** 目标与动机。 */
522
- goals: string
523
- /** 关系网:[角色名](关系)。 */
524
- relations: string[]
525
- /** 成长线:阶段 → 说明(可含章节)。 */
526
- arc: string[]
527
- /** 知情度:该角色已经知道的信息。 */
528
- knowledge: string[]
529
- /** 首次出场章节(编年录聚合,可手动修正)。 */
530
- firstChapter?: number
531
- /** 动漫形象描述词(AI 绘图用:中文描述 + 英文标签 + 关键外貌标签)。 */
532
- imagePrompt?: {
533
- /** 中文外貌描述:连贯一段(发色/瞳色/服装/气质/标志物)。 */
534
- zh: string
535
- /** 英文绘图标签:booru 风格逗号分隔。 */
536
- en: string
537
- /** 中文关键标签(发色/瞳色/服装/气质/标志物)。 */
538
- tags: string[]
539
- /** 依据来源说明(哪几章哪些描写)。 */
540
- source?: string
541
- }
542
- /** 角色参考图(dataURL 或 URL)。用于漫画/漫剧出图时锁定角色一致性。 */
543
- imageUrl?: string
544
- /** 角色图集(图像锚点):立绘/四视图/表情/场景/细节等,label 标注用途。 */
545
- gallery?: RoleImage[]
546
- /** 该角色所需的情绪表情清单(提炼时 LLM 补全 6-12 个,如"疲惫/麻木/压抑悲伤")。 */
547
- expressions?: string[]
548
- /** LLM 精修的四类生图提示词包(前端拼装版之外的高质量版,promptKit 接口生成)。 */
549
- promptKit?: {
550
- /** 立绘:全身/半身正视图。 */
551
- portrait: { zh: string; en: string }
552
- /** 四视图:正面/侧面/背面设定表。 */
553
- sheet: { zh: string; en: string }
554
- /** 表情:同一脸部锚换情绪,每表情一段。 */
555
- expressions: { name: string; zh: string; en: string }[]
556
- /** 细节:标志物局部特写。 */
557
- details: { zh: string; en: string }
558
- }
559
- /** 漫画/漫剧重要性:main=必须建卡保证一致;support=有锚点即可;extra=路人随机生成不约束。 */
560
- importance?: 'main' | 'support' | 'extra'
561
- }
562
-
563
- /** 角色图集条目:一张已定型的角色图(图像锚点)。 */
564
- export interface RoleImage {
565
- /** 用途标签:立绘 / 四视图 / 表情-疲惫 / 场景 / 细节 等。 */
566
- label: string
567
- /** dataURL 或 URL。 */
568
- dataUrl: string
569
- }
570
-
571
- /** 场景库条目:从正文提炼的「镜头场景」视觉锚点(漫剧分镜/生图用)。 */
572
- export interface SceneCard {
573
- /** 场景名(唯一键),如「旧茶渡·地下石殿」。 */
574
- name: string
575
- /** 一句话定位:空间/氛围/功能。 */
576
- summary: string
577
- /** 幕归属:第一幕·后场 / 第二幕·卖场 / …(便于按剧情段落组织)。 */
578
- act?: string
579
- /** 时间光态:夜间闭店后 / 雨夜 / 凌晨 / 频闪灯… */
580
- moment?: string
581
- /** 关键情节镜头 1-3 条:该场景拍什么(人物动作+情绪+镜头推进)。 */
582
- beats?: string[]
583
- /** 人物在场状态:主角/关键角色在该场景的状态一句话。 */
584
- characterState?: string
585
- /** 环境构成:空间结构/陈设/标志物。 */
586
- elements: string[]
587
- /** 色调与光影(含 HEX 色板,可空)。 */
588
- palette: string[]
589
- /** 氛围关键词:压抑/神秘/空旷… */
590
- moods: string[]
591
- /** 中文生图提示词(连贯一段,写实电影感)。 */
592
- zh: string
593
- /** 英文生图提示词(逗号分隔标签)。 */
594
- en: string
595
- /** 关键标签。 */
596
- tags: string[]
597
- /** 依据来源(哪几章哪些描写)。 */
598
- source?: string
599
- /** 场景图集(图像锚点):全景/局部/氛围 等。 */
600
- gallery?: RoleImage[]
601
- }
602
-
603
- /** POST /scenes 请求:场景库提炼 / 采纳 / 更新 / 删除 / 图集。 */
604
- export interface ScenesRequest {
605
- op: 'extract' | 'adopt' | 'update' | 'remove' | 'image' | 'removeImage'
606
- /** adopt / update 时传入的场景卡(adopt 可修改后采纳)。 */
607
- scene?: SceneCard
608
- /** remove / image 时的场景名。 */
609
- name?: string
610
- /** op='image' 时的图片 dataURL 与用途标签(全景/局部/氛围)。 */
611
- dataUrl?: string
612
- label?: string
613
- }
614
-
615
- /** POST /visual-rules 请求:视觉世界观规则提炼 / 保存。 */
616
- export interface VisualRulesRequest {
617
- op: 'extract' | 'save'
618
- /** op=save 时的规则数组。 */
619
- rules?: string[]
620
- }
621
-
622
- /** POST /visual-rules 响应。 */
623
- export interface VisualRulesResponse {
624
- rules: string[]
625
- }
626
-
627
- /** POST /scenes 响应。 */
628
- export interface ScenesResponse {
629
- scenes: SceneCard[]
630
- /** op=extract 时的 AI 候选场景。 */
631
- candidates?: SceneCard[]
632
- }
633
-
634
- /** POST /roles 请求:角色库增删改 + AI 提炼 + 参考图上传。 */
635
- export interface RolesRequest {
636
- op: 'extract' | 'adopt' | 'update' | 'remove' | 'visual' | 'image' | 'removeImage' | 'imageGenerate' | 'promptKit'
637
- /** adopt / update 时传入的角色(adopt 可修改后采纳)。 */
638
- role?: RoleRecord
639
- /** remove 时的角色名。 */
640
- name?: string
641
- /** op='image' 时的参考图 dataURL。 */
642
- dataUrl?: string
643
- /** op='image' 时的图集用途标签(立绘/四视图/表情-x/场景/细节);缺省视为角色参考图(imageUrl)。 */
644
- label?: string
645
- /** op='imageGenerate' 时的漫画风格预设 id(用于统一角色图与漫画页风格)。 */
646
- style?: string
647
- }
648
-
649
- /** POST /roles 响应。 */
650
- export interface RolesResponse {
651
- roles: RoleRecord[]
652
- /** op=extract 时的 AI 候选角色。 */
653
- candidates?: RoleRecord[]
654
- /** op=visual 时的动漫形象描述词(已写入角色卡)。 */
655
- visual?: RoleRecord['imagePrompt']
656
- /** op=promptKit 时的四类提示词精修包(已写入角色卡)。 */
657
- promptKit?: RoleRecord['promptKit']
658
- /** op=image 时的角色参考图 dataURL。 */
659
- imageUrl?: string
660
- }
661
-
662
- /** POST /bible/patch 请求:局部修补设定圣经。 */
663
- export interface BiblePatchRequest {
664
- worldRules?: string[]
665
- redLines?: string[]
666
- style?: string[]
667
- /** 角色卡整体替换(人物志编辑知情度等)。 */
668
- characters?: CharacterCard[]
669
- }
670
-
671
- /** POST /blurb 请求:AI 生成/补全或手动保存小说简介。 */
672
- export interface BlurbRequest {
673
- action: 'generate' | 'save'
674
- /** 已写好的开头(AI 补全时使用;留空 = 全量生成)。 */
675
- partial?: string
676
- /** 手动保存的完整简介(action=save 时)。 */
677
- text?: string
678
- }
679
-
680
- /** POST /chapter/check|save 请求:审查/保存手动编辑的正文。 */
681
- export interface ChapterTextRequest {
682
- chapterNo: number
683
- /** 当前编辑中的正文全文。 */
684
- text: string
685
- /** 保存时携带:已在工作区审查过的报告(沿用落盘,不重复审);缺省则保存后自动正式审稿一次。 */
686
- report?: ReviewReport
687
- /** 审查/验证时携带:上一轮审稿报告。传入后进入「验证模式」——逐条核对原意见是否解决、
688
- * 只挑新增 high,不再全新找茬(防止"越修 high 越多")。 */
689
- previousReport?: ReviewReport
690
- }
691
-
692
- /** POST /chapter/save 响应。 */
693
- export interface ChapterSaveResponse {
694
- ok: boolean
695
- chars: number
696
- file: string
697
- /** 落盘的审稿报告(沿用工作区报告或保存后自动审稿)。 */
698
- report?: ReviewReport
699
- }
700
-
701
- /** POST /cover 请求:上传或移除封面。 */
702
- export interface CoverRequest {
703
- action: 'upload' | 'remove'
704
- /** 上传时:data:image/...;base64,... 格式的图片数据。 */
705
- dataUrl?: string
706
- }
707
-
708
- /** POST /rename 请求:重命名当前书。 */
709
- export interface RenameRequest {
710
- bookName: string
711
- }
712
-
713
- /** 大世界:一个境界等级。 */
714
- export interface WorldRealm {
715
- /** 境界名(练气/筑基/金丹…)。 */
716
- name: string
717
- /** 描述:突破条件/寿命/标志等。 */
718
- description: string
719
- }
720
-
721
- /** 大世界:一个地理区域。 */
722
- export interface WorldRegion {
723
- name: string
724
- description: string
725
- /** 关联势力名(可空)。 */
726
- faction?: string
727
- }
728
-
729
- /** 大世界:一方势力。 */
730
- export interface WorldFaction {
731
- name: string
732
- /** 类型:宗门/家族/王朝/组织… */
733
- kind: string
734
- description: string
735
- /** 驻地区域(可空)。 */
736
- region?: string
737
- }
738
-
739
- /** 大世界结构化数据。 */
740
- export interface WorldState {
741
- realms: WorldRealm[]
742
- regions: WorldRegion[]
743
- factions: WorldFaction[]
744
- }
745
-
746
- /** POST /world 请求:AI 提炼或手动保存。 */
747
- export interface WorldRequest {
748
- action: 'generate' | 'save'
749
- /** action=save 时的完整世界数据。 */
750
- world?: WorldState
751
- }
752
-
753
- /** GET /cover 响应:封面的 dataUrl(无封面为 null)。 */
754
- export interface CoverResponse {
755
- dataUrl: string | null
756
- }
757
-
758
- /** The persisted project: outline + bible + plan + progress. */
759
- export interface ProjectState {
760
- /** Book title (first non-empty line of the outline, usually). */
761
- bookName: string
762
- /** Full outline text (docx-extracted or pasted). */
763
- outline: string
764
- /** Source outline path when loaded from a docx. */
765
- outlinePath?: string
766
- /** Structured story bible (worldbuilding), if generated. */
767
- bible?: StoryBible
768
- /** Volumes, if planned. */
769
- volumes?: Volume[]
770
- /** Chapter plan. */
771
- chapters: ChapterPlan[]
772
- /** Foreshadowing threads. */
773
- foreshadows: Foreshadow[]
774
- /** 写作资产(题材基底/推进模式/反AI规则/写法资产)。 */
775
- assets?: ProjectAssets
776
- /** 事实库/时间线:每章生成后抽取,注入后续章节保持一致性。 */
777
- facts?: ChapterFact[]
778
- /** 小说简介(面向读者的作品门面,AI 生成或手动保存)。 */
779
- blurb?: string
780
- /** 封面文件名(相对输出目录,如 cover.png)。 */
781
- coverPath?: string
782
- /** 大世界结构化数据(境界体系/区域/势力)。 */
783
- world?: WorldState
784
- /** 剧情线(主线/支线/人物线/悬念线)。 */
785
- plotlines?: Plotline[]
786
- /** 角色库(作者维护 + AI 提炼的主表)。 */
787
- roles?: RoleRecord[]
788
- /** 场景库(作者维护 + AI 提炼的主表)。 */
789
- scenes?: SceneCard[]
790
- /** 视觉世界观规则(生图/生视频必须遵守,从道藏提炼,注入所有提示词)。 */
791
- visualRules?: string[]
792
- /** 人物志:角色当前状态聚合结果(从编年录刷新后存档,打开页面直接显示)。 */
793
- roleStatus?: RoleStatusCard[]
794
- /** 漫剧分镜结果缓存:章号 → 分镜(持久化,刷新不丢)。 */
795
- /** 漫剧分集计划缓存:卷号/0=全书 → 分集计划(持久化,刷新不丢)。 */
796
- /** 漫画脚本缓存:章号 → 漫画脚本(持久化,刷新不丢)。 */
797
- /** ISO timestamps. */
798
- createdAt: string
799
- updatedAt: string
800
- }
801
-
802
- /** Runtime config surface exposed to the panel (subset of plugin Config). */
803
- export interface NovelConfig {
804
- /** Absolute path of the default docx outline to load. */
805
- outlinePath: string
806
- /** Absolute output directory for chapters + project state. */
807
- outputDir: string
808
- /** LLM provider route (e.g. deepseek-official). */
809
- provider: string
810
- /** LLM model id (e.g. deepseek-v4-flash). */
811
- model: string
812
- /** LLM reasoning effort: off = no thinking; low/high/max = thinking intensity. */
813
- reasoningEffort: 'off' | 'low' | 'high' | 'max'
814
- /** Target characters per chapter. */
815
- chapterChars: number
816
- /** Max output tokens per chapter call. */
817
- maxTokens: number
818
- /** Review pass threshold (0-100). */
819
- reviewPassScore: number
820
- /** Whether generation auto-runs review after writing. */
821
- autoReview: boolean
822
- /** Whether generation auto-runs the author review (hook/continuity/trend) after writing. */
823
- autoAuthorReview: boolean
824
- /** 修订/润色产出草稿后是否自动附带一次 AI 审查(工作区显示新稿评分与剩余问题)。 */
825
- autoReviewAfterRevise: boolean
826
- /** 豆包/Seedream 生图 API Key(保存在服务端配置,不暴露给前端明文回显)。 */
827
- imageApiKey?: string
828
- /** 豆包/Seedream 生图模型 ID(如 doubao-seedream-5-0-pro-260628)。 */
829
- imageApiModel?: string
830
- /** 是否启用豆包生图(默认关,避免误调用付费 API)。 */
831
- imageApiEnabled?: boolean
832
- }
833
-
834
- /** GET /status response. */
835
- export interface StatusResponse {
836
- config: NovelConfig
837
- /** The persisted project, when one exists in the output dir. */
838
- project?: ProjectState
839
- /** Chapter files already on disk (basenames, sorted). */
840
- generatedFiles: string[]
841
- /** 全书质检实时状态(用于面板/外部读取进度)。 */
842
- audit?: AuditStatus
843
- }
844
-
845
- /** 生产单状态(生产单 = 区间批量生产执行器:计划补足 + 逐章生成 + 被拒分级处理)。 */
846
- export interface RunState {
847
- runId: string
848
- /** 区间起点(含)。 */
849
- startNo: number
850
- /** 区间终点(含)。 */
851
- endNo: number
852
- status: 'running' | 'paused' | 'done' | 'stopped' | 'error'
853
- /** 当前处理到的章号(已 approved 的章会快进)。 */
854
- currentNo: number
855
- stats: {
856
- /** 新生成(含审稿)的章数。 */
857
- generated: number
858
- /** 被拒后按意见修订并通过的章数。 */
859
- revised: number
860
- /** 被拒后豁免通过(无 high)的章数。 */
861
- exempted: number
862
- /** error 后重新生成的章数。 */
863
- regenerated: number
864
- /** 生成失败的章数。 */
865
- error: number
866
- }
867
- /** 两轮修订仍不过、保留草稿待人工的章号。 */
868
- pendingManual: number[]
869
- /** 运行日志(保留最近 300 条)。 */
870
- log: Array<{ at: string; text: string }>
871
- startedAt: string
872
- updatedAt: string
873
- error?: string
874
- }
875
-
876
- /** POST /run/start request. */
877
- export interface RunStartRequest {
878
- /** 起始章号(默认 1)。 */
879
- startNo?: number
880
- /** 结束章号(含;超出计划时自动补计划)。 */
881
- endNo?: number
882
- /** 或指定新增章数(从当前最后一章 +1 起)。 */
883
- count?: number
884
- }
885
-
886
- /** POST /run/control request. */
887
- export interface RunControlRequest {
888
- action: 'pause' | 'resume' | 'stop'
889
- }
890
-
891
- /** POST /load-outline request: either a docx path or raw text. */
892
- export interface LoadOutlineRequest {
893
- /** Absolute docx path; defaults to the configured outline path. */
894
- path?: string
895
- /** Raw outline text (takes precedence over path when present). */
896
- text?: string
897
- }
898
-
899
- /** POST /load-outline response. */
900
- export interface LoadOutlineResponse {
901
- outline: string
902
- bookName: string
903
- chars: number
904
- path?: string
905
- }
906
-
907
- /** POST /plan request. */
908
- export interface PlanRequest {
909
- /** Outline to plan from; defaults to the persisted project's outline. */
910
- outline?: string
911
- /** Number of chapters to plan (default: 30). */
912
- chapterCount?: number
913
- /** Volume to plan (1-based); when given, plans only that volume's chapters. */
914
- volume?: number
915
- }
916
-
917
- /** POST /plan response. */
918
- export interface PlanResponse {
919
- chapters: ChapterPlan[]
920
- volumes?: Volume[]
921
- }
922
-
923
- /** POST /volumes request/response. */
924
- export interface VolumesRequest {
925
- /** Outline to split into volumes; defaults to the project outline. */
926
- outline?: string
927
- }
928
- export interface VolumesResponse {
929
- volumes: Volume[]
930
- }
931
-
932
- /** POST /bible request/response. */
933
- export interface BibleRequest {
934
- /** Outline to extract from; defaults to the project outline. */
935
- outline?: string
936
- }
937
- export interface BibleResponse {
938
- bible: StoryBible
939
- }
940
-
941
- /** POST /generate request: one chapter of the current project. */
942
- export interface GenerateRequest {
943
- chapterNo: number
944
- /** When true, skips the auto-review step. */
945
- skipReview?: boolean
946
- }
947
-
948
- /** One NDJSON frame of a generation/review/rewrite stream. */
949
- export type JobFrame =
950
- | { type: 'start'; no: number; title: string }
951
- | { type: 'delta'; text: string }
952
- | { type: 'progress'; chars: number }
953
- | { type: 'done'; no: number; file: string; chars: number; title: string }
954
- | { type: 'review'; no: number; report: ReviewReport }
955
- | { type: 'author-review'; no: number; review: AuthorReview }
956
- | { type: 'author-backfill-done'; count: number }
957
- | { type: 'rewritten'; no: number; file: string; chars: number }
958
- /** 润色/重写完成,产物作为待确认草稿(尚未覆盖正文)。 */
959
- | { type: 'drafted'; no: number; chars: number; draft: string }
960
- | { type: 'error'; no: number; message: string }
961
-
962
- /** POST /review request: review one written chapter. */
963
- export interface ReviewRequest {
964
- chapterNo: number
965
- }
966
-
967
- /** POST /rewrite request: rewrite one chapter (optionally per review issues). */
968
- export interface RewriteRequest {
969
- chapterNo: number
970
- /** Free-form instructions; defaults to fixing the review's high issues. */
971
- instructions?: string
972
- /**
973
- * 局部修订:正文中的一段原文(无需完全精确,取一个自然段内的片段即可)。
974
- * 提供时只重写该段,其余正文保持不变;不提供时整章重写。
975
- */
976
- target?: string
977
- }
978
-
979
- /** POST /polish request: de-AI-ify one chapter. */
980
- export interface PolishRequest {
981
- chapterNo: number
982
- }
983
-
984
- /** POST /draft/apply | /draft/discard request: 采纳或放弃待确认草稿。 */
985
- export interface DraftDecisionRequest {
986
- chapterNo: number
987
- /** apply 时可携带审查报告(沿用结论定状态;不携带则置 written)。 */
988
- report?: ReviewReport
989
- }
990
-
991
- /** POST /summary request: (re)generate a chapter summary. */
992
- export interface SummaryRequest {
993
- chapterNo: number
994
- }
995
-
996
- /** POST /foreshadow request: create, update, or AI-suggest foreshadows. */
997
- export interface ForeshadowRequest {
998
- /** When true, runs the LLM suggestion pass (ignores other fields). */
999
- suggest?: boolean
1000
- /** When given, updates that foreshadow instead of creating one. */
1001
- id?: string
1002
- description?: string
1003
- plantedChapter?: number
1004
- targetChapter?: number
1005
- status?: Foreshadow['status']
1006
- resolvedNote?: string
1007
- }
1008
- export interface ForeshadowResponse {
1009
- foreshadows: Foreshadow[]
1010
- }
1011
-
1012
- /** GET /chapter response. */
1013
- export interface ChapterResponse {
1014
- no: number
1015
- title: string
1016
- markdown: string
1017
- }
1018
-
1019
- /** POST /export request/response. */
1020
- export interface ExportRequest {
1021
- format: 'txt' | 'md'
1022
- }
1023
- export interface ExportResponse {
1024
- file: string
1025
- chars: number
1026
- chapters: number
1027
- }
1028
-
1029
- /** POST /config request: patch any subset of the runtime config. */
1030
- export interface ConfigPatch {
1031
- outlinePath?: string
1032
- outputDir?: string
1033
- provider?: string
1034
- model?: string
1035
- reasoningEffort?: 'off' | 'low' | 'high' | 'max'
1036
- chapterChars?: number
1037
- maxTokens?: number
1038
- reviewPassScore?: number
1039
- autoReview?: boolean
1040
- autoAuthorReview?: boolean
1041
- autoReviewAfterRevise?: boolean
1042
- imageApiKey?: string
1043
- imageApiModel?: string
1044
- imageApiEnabled?: boolean
1045
- }
1046
-
1047
- // ------------------------------------------------------------ assistant
1048
-
1049
- /** One assistant conversation message (persisted per project). */
1050
- export interface AssistantMessage {
1051
- role: 'user' | 'assistant' | 'tool'
1052
- /** Message text (tool messages carry the tool result). */
1053
- content: string
1054
- /** ISO timestamp. */
1055
- ts: string
1056
- /** For tool messages: which tool ran. */
1057
- tool?: string
1058
- }
1059
-
1060
- /** POST /assistant request: one user turn. */
1061
- export interface AssistantRequest {
1062
- message: string
1063
- }
1064
-
1065
- /** One NDJSON frame of the assistant stream. */
1066
- export type AssistantFrame =
1067
- | { type: 'delta'; text: string }
1068
- | { type: 'tool'; name: string; status: 'start' | 'done' | 'error'; detail?: string }
1069
- /** Live output while a tool runs (e.g. chapter text being generated). */
1070
- | { type: 'toolDelta'; name: string; text: string }
1071
- | { type: 'done' }
1072
- | { type: 'error'; message: string }
1073
-
1074
- /** GET /assistant-history response. */
1075
- export interface AssistantHistoryResponse {
1076
- messages: AssistantMessage[]
1077
- }
1078
-
1079
- // ---------------------------------------------------------- writing assets
1080
-
1081
- /** 题材基底库:一本书属于哪个阅读市场。树形(题材→子题材→下级)。 */
1082
- export interface GenreNode {
1083
- /** 题材名称(标签,如「仙侠修真」「都市异能」)。 */
1084
- name: string
1085
- /** 题材特征、常见爽点、叙事重心或读者期待。 */
1086
- description: string
1087
- /** 子题材。 */
1088
- children: GenreNode[]
1089
- }
1090
-
1091
- /** 推进模式库:读者为什么继续看下一章。 */
1092
- export interface ProgressionMode {
1093
- /** 模式名称(如「升级变强」「经营扩张」「解谜揭露」)。 */
1094
- name: string
1095
- /** 核心驱动力:靠什么制造追读动力。 */
1096
- driver: string
1097
- /** 读者期待:每隔几章获得什么变化或回报。 */
1098
- readerExpectation: string
1099
- /** 常见兑现方式(爽点如何落地)。 */
1100
- payoffs: string[]
1101
- /** 节奏风险:最怕什么(重复升级、冲突变弱、谜题拖太久…)。 */
1102
- risks: string[]
1103
- /** 主模式或辅助模式。 */
1104
- primary: boolean
1105
- }
1106
-
1107
- /** 反 AI 规则:一条「要避免的问题 + 修正方向」。 */
1108
- export interface AntiAiRule {
1109
- /** 规则名(如「禁止解释型心理描写」「AI 高频套话」)。 */
1110
- name: string
1111
- /** 要避免的表达问题,具体可检查。 */
1112
- avoid: string
1113
- /** 推荐修正方向。 */
1114
- fix: string
1115
- /** 命中即告警的具体表达模式(用于审稿逐条核对与去 AI 味检测)。 */
1116
- detectPatterns?: string[]
1117
- /** 是否内置全局规则(内置规则随插件发布,项目规则为用户自定义)。 */
1118
- builtin?: boolean
1119
- }
1120
-
1121
- /** 预置写法模板(来自 AI-Novel-Writing-Assistant 内置数据,一键绑定无需样本文本)。 */
1122
- export interface StyleTemplate {
1123
- /** 模板 key(如 power-up-escalation)。 */
1124
- key: string
1125
- /** 模板名(如「爽文递进推进流」)。 */
1126
- name: string
1127
- /** 模板说明。 */
1128
- description: string
1129
- /** 分类(如「爽文流」「悬疑流」)。 */
1130
- category: string
1131
- /** 适用题材。 */
1132
- applicableGenres: string[]
1133
- /** 叙述规则。 */
1134
- proseRules: string[]
1135
- /** 角色/台词规则。 */
1136
- dialogueRules: string[]
1137
- /** 语言规则。 */
1138
- languageRules: string[]
1139
- /** 节奏规则。 */
1140
- rhythmRules: string[]
1141
- /** 该模板默认绑定的反 AI 规则 key(内置规则名)。 */
1142
- defaultAntiAiRuleKeys: string[]
1143
- }
1144
-
1145
- /** 写法引擎:从样本文本提取的叙事风格资产。 */
1146
- export interface StyleAsset {
1147
- /** 资产名(如「林越式痞坏」「冷峻猎手风」)。 */
1148
- name: string
1149
- /** 叙述视角与句式节奏。 */
1150
- proseRules: string[]
1151
- /** 角色台词风格。 */
1152
- dialogueRules: string[]
1153
- /** 描写密度与情绪表达。 */
1154
- descriptionRules: string[]
1155
- /** 表达边界(不要做什么)。 */
1156
- boundaries: string[]
1157
- /** 来源样本文本(可空)。 */
1158
- sourceText?: string
1159
- /** 创建时间。 */
1160
- createdAt: string
1161
- }
1162
-
1163
- /** 项目写作资产(题材基底 + 推进模式 + 反 AI 规则 + 写法资产)。 */
1164
- export interface ProjectAssets {
1165
- /** 本书选用的题材(可以是题材基底库中某节点名)。 */
1166
- genre?: GenreNode
1167
- /** 主推进模式。 */
1168
- primaryProgression?: ProgressionMode
1169
- /** 辅助推进模式。 */
1170
- auxiliaryProgressions: ProgressionMode[]
1171
- /** 生效的反 AI 规则(内置 + 自定义)。 */
1172
- antiAiRules: AntiAiRule[]
1173
- /** 绑定的写法资产。 */
1174
- styleAssets: StyleAsset[]
1175
- /** 资产更新时间。 */
1176
- updatedAt?: string
1177
- }
1178
-
1179
- /** GET /assets response(含全局题材库与反 AI 规则库)。 */
1180
- export interface AssetsResponse {
1181
- projectAssets: ProjectAssets
1182
- /** 全局题材基底库(可复用资产,跨书)。 */
1183
- genreLibrary: GenreNode[]
1184
- /** 全局反 AI 规则库(内置默认规则)。 */
1185
- antiAiLibrary: AntiAiRule[]
1186
- /** 预置写法模板(一键绑定,无需样本文本)。 */
1187
- styleTemplates: StyleTemplate[]
1188
- /** 内置推进模式候选。 */
1189
- progressionLibrary: ProgressionMode[]
1190
- }
1191
-
1192
- /** POST /assets request:更新项目写作资产(部分字段可选)。 */
1193
- export interface AssetsPatch {
1194
- genre?: GenreNode
1195
- primaryProgression?: ProgressionMode
1196
- auxiliaryProgressions?: ProgressionMode[]
1197
- antiAiRules?: AntiAiRule[]
1198
- styleAssets?: StyleAsset[]
1199
- }
1200
-
1201
- /** POST /style-engine request:从样本文本提取写法资产。 */
1202
- export interface StyleEngineRequest {
1203
- /** 样本文本(风格来源)。 */
1204
- sampleText: string
1205
- /** 资产名(可选,默认「风格资产 N」)。 */
1206
- name?: string
1207
- }
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
+ /** 导入已有项目目录(含 novel-project.json)到书架。 */
40
+ bookshelfImportDir: '/api/dsh-novel-forge/bookshelf/import-dir',
41
+ /** 导入 txt/md 全本:拆章建项目并登记书架。 */
42
+ bookshelfImportText: '/api/dsh-novel-forge/bookshelf/import-text',
43
+ /** 导入 txt/md 全本:拆章预览(不落盘)。 */
44
+ bookshelfImportTextPreview: '/api/dsh-novel-forge/bookshelf/import-text/preview',
45
+ /** 重置项目(可选携带新大纲):清空设定/卷/章节/伏笔/资产/事实库。 */
46
+ reset: '/api/dsh-novel-forge/reset',
47
+ /** 全书一致性质检:LLM 扫描已生成章节,输出矛盾问题清单。 */
48
+ audit: '/api/dsh-novel-forge/audit',
49
+ /** 角色卡刷新:基于事实库与各章摘要聚合角色当前状态。 */
50
+ charactersRefresh: '/api/dsh-novel-forge/characters/refresh',
51
+ /** 事实库回填:对历史已生成章节批量抽取事实(旧章节无事实记录时用)。 */
52
+ factsBackfill: '/api/dsh-novel-forge/facts/backfill',
53
+ /** 设定圣经局部修补(如世界观规则编辑)。 */
54
+ biblePatch: '/api/dsh-novel-forge/bible/patch',
55
+ /** 小说简介:生成(AI)/补全(AI)/保存。 */
56
+ blurb: '/api/dsh-novel-forge/blurb',
57
+ /** 重命名当前书(同步项目与书架条目)。 */
58
+ rename: '/api/dsh-novel-forge/rename',
59
+ /** 大世界:AI 提炼 / 保存结构化数据(境界/区域/势力)。 */
60
+ world: '/api/dsh-novel-forge/world',
61
+ /** 封面:GET 读取(dataUrl)/ POST 上传或移除。 */
62
+ cover: '/api/dsh-novel-forge/blurb/cover',
63
+ /** 剧情线管理:增删改 + 关联章节。 */
64
+ plotlines: '/api/dsh-novel-forge/plotlines',
65
+ /** 角色库:AI 提炼 / 采纳 / 更新 / 删除。 */
66
+ roles: '/api/dsh-novel-forge/roles',
67
+ scenes: '/api/dsh-novel-forge/scenes',
68
+ visualRules: '/api/dsh-novel-forge/visual-rules',
69
+ /** 作者复盘补跑:对已写章节补齐 authorReview(全书流式 / 单章 JSON)。 */
70
+ reviewBackfill: '/api/dsh-novel-forge/review/backfill',
71
+ /** 章节复位:generating 卡死 → pending(可重新生成)。 */
72
+ chapterReset: '/api/dsh-novel-forge/chapter/reset',
73
+ /** 章节直接通过:作者对 rejected/written 章节行使最终决定权。 */
74
+ chapterApprove: '/api/dsh-novel-forge/chapter/approve',
75
+ /** 敏感词检查:全书已写章节或指定文本。 */
76
+ sensitiveCheck: '/api/dsh-novel-forge/sensitive-check',
77
+ /** 开书想法 → AI 补全大纲:输入一句话想法,生成 2-3 个可选大纲方案。 */
78
+ outlineSuggest: '/api/dsh-novel-forge/outline/suggest',
79
+ /** 反推大纲:从已写章节正文反向生成全书总纲(NDJSON 流)。 */
80
+ outlineReverse: '/api/dsh-novel-forge/outline/reverse',
81
+ /** 拆书分析:对已写章节做结构/人物/文风/卖点四维体检(两阶段:源笔记→分节分析)。 */
82
+ breakdown: '/api/dsh-novel-forge/breakdown',
83
+ /** 漫剧分镜生成:章节 → 角色锚点 + 分镜表(可适配豆包/Seedance/SD)。 */
84
+ /** 漫剧分集计划:读一卷 → 按故事弧线分集(高潮拆集/过渡并章)。 */
85
+ /** 漫画脚本:章节 → 分页分格漫画脚本(含角色视觉锚点)。 */
86
+ /** 生产单:启动批量生产(计划补足 + 逐章生成 + 被拒分级处理)。 */
87
+ runStart: '/api/dsh-novel-forge/run/start',
88
+ /** 生产单控制:pause / resume / stop。 */
89
+ runControl: '/api/dsh-novel-forge/run/control',
90
+ /** 生产单状态(含进度统计与日志)。 */
91
+ runStatus: '/api/dsh-novel-forge/run/status',
92
+ config: '/api/dsh-novel-forge/config',
93
+ openFolder: '/api/dsh-novel-forge/open-folder',
94
+ } as const
95
+
96
+ /** 书架:一本书的条目。 */
97
+ export interface BookEntry {
98
+ /** 稳定 id。 */
99
+ id: string
100
+ /** 书名。 */
101
+ bookName: string
102
+ /** 该书输出目录(独立项目目录)。 */
103
+ outputDir: string
104
+ /** 创建时间。 */
105
+ createdAt: string
106
+ /** 最后活动时间。 */
107
+ updatedAt: string
108
+ }
109
+
110
+ /** 书架快照(含每本书的进度摘要)。 */
111
+ export interface BookshelfSnapshot {
112
+ books: Array<BookEntry & { done: number; total: number; hasProject: boolean; hasCover: boolean; blurb?: string }>
113
+ /** 当前激活的书 id(无则 null)。 */
114
+ activeBookId: string | null
115
+ }
116
+
117
+ /** POST /bookshelf 请求:创建新书。 */
118
+ export interface BookCreateRequest {
119
+ bookName: string
120
+ outputDir?: string
121
+ /** 开书向导:创建时直接导入的大纲文本(提供则立即建立项目)。 */
122
+ outline?: string
123
+ }
124
+
125
+ /** POST /reset 请求:重置项目(可选更新大纲)。 */
126
+ export interface ResetRequest {
127
+ /** 新大纲文本;提供则替换 outline,否则保留原大纲。 */
128
+ outline?: string
129
+ }
130
+
131
+ /** POST /bookshelf/activate 请求:切换当前书。 */
132
+ export interface BookActivateRequest {
133
+ id: string
134
+ }
135
+
136
+ /** POST /bookshelf/remove 请求:移除书架条目。 */
137
+ export interface BookRemoveRequest {
138
+ id: string
139
+ }
140
+
141
+ /** POST /bookshelf/import-dir 请求:导入已有项目目录。 */
142
+ export interface BookImportDirRequest {
143
+ /** 项目目录(须含 novel-project.json)。 */
144
+ outputDir: string
145
+ }
146
+
147
+ /** POST /bookshelf/import-dir 响应。 */
148
+ export interface BookImportDirResponse {
149
+ book: BookEntry
150
+ /** true = 目录已在书架中(本次为重新激活)。 */
151
+ existed: boolean
152
+ }
153
+
154
+ /** POST /bookshelf/import-text 请求:导入 txt/md 全本。两种模式二选一:
155
+ * - filePath:服务器本地文件路径;
156
+ * - text + fileName:浏览器上传的全文内容(fileName 用于推断书名)。
157
+ */
158
+ export interface BookImportTextRequest {
159
+ /** 模式一:源文件绝对路径(txt 或 md)。 */
160
+ filePath?: string
161
+ /** 模式二:浏览器上传的全文内容。 */
162
+ text?: string
163
+ /** 模式二:原文件名(txt/md),用于推断书名与显示。 */
164
+ fileName?: string
165
+ /** 输出目录;缺省为 ~/.dsh/novels/书名。 */
166
+ outputDir?: string
167
+ }
168
+
169
+ /** POST /bookshelf/import-text 响应。 */
170
+ export interface BookImportTextResponse {
171
+ bookName: string
172
+ /** 成功拆出的章节数。 */
173
+ chapters: number
174
+ /** 因内容过短被跳过的章节标题列表。 */
175
+ skipped: string[]
176
+ /** 登记后的书架条目。 */
177
+ book: BookEntry
178
+ }
179
+
180
+ /** POST /bookshelf/import-text/preview 请求:上传全文做拆章预览(不落盘)。 */
181
+ export interface BookImportTextPreviewRequest {
182
+ text: string
183
+ /** 原文件名(txt/md),用于推断书名。 */
184
+ fileName?: string
185
+ }
186
+
187
+ /** POST /bookshelf/import-text/preview 响应。 */
188
+ export interface BookImportTextPreviewResponse {
189
+ /** 预计书名(fileName 去扩展名)。 */
190
+ bookName: string
191
+ /** 识别出的章节(已按正文长度过滤过短章节)。 */
192
+ chapters: Array<{ no: number; title: string; chars: number }>
193
+ /** 因内容过短被跳过的章节标题列表。 */
194
+ skipped: string[]
195
+ }
196
+
197
+
198
+ /** Chapter lifecycle states (the writing pipeline's state machine). */
199
+ export type ChapterStatus =
200
+ | 'pending' // planned, not started
201
+ | 'generating' // LLM writing right now
202
+ | 'written' // body on disk, awaiting review
203
+ | 'reviewing' // review in progress
204
+ | 'approved' // passed review (or user-approved)
205
+ | 'rejected' // review found problems
206
+ | 'error' // generation failed
207
+
208
+ /** One chapter in the plan. */
209
+ export interface ChapterPlan {
210
+ /** 1-based chapter number (stable identity; files are named from it). */
211
+ no: number
212
+ /** Volume this chapter belongs to (1-based; 0 = unassigned). */
213
+ volume: number
214
+ /** Chapter title, decided by the LLM plan step. */
215
+ title: string
216
+ /** Story beats / plot points for this chapter (model-facing guidance). */
217
+ beats: string
218
+ /** Target character count (defaults to the configured chapter size). */
219
+ targetChars: number
220
+ /** Generation/review state. */
221
+ status: ChapterStatus
222
+ /** 进入 generating 的时间(用于超时自动复位;未在生成时无此字段)。 */
223
+ generatingAt?: string
224
+ /** Actual character count once generated. */
225
+ chars?: number
226
+ /** Failure message when status is 'error'. */
227
+ error?: string
228
+ /** Output file name once generated (relative to the output dir). */
229
+ file?: string
230
+ /** LLM summary of the chapter (narrative memory for later chapters). */
231
+ summary?: string
232
+ /** Latest review report (present once reviewed). */
233
+ review?: ReviewReport
234
+ /** 作者复盘:钩子兑现/结尾钩子/剧情线推进/连续性/节奏趋势(生成后自动)。 */
235
+ authorReview?: AuthorReview
236
+ /**
237
+ * 待确认草稿:润色(去AI味)或整章重写的产物正文。生成时先存这里,
238
+ * 用户看过对比后点「采纳」才覆盖正文文件;点「放弃」则丢弃。刷新页面不丢失。
239
+ */
240
+ pendingDraft?: string
241
+ }
242
+
243
+ /** 作者复盘:叙事结构层面的逐章检查(钩子/推进/连续性/趋势)。 */
244
+ export interface AuthorReview {
245
+ /** 上一章结尾钩子是否在本章兑现。 */
246
+ hookHonored: boolean
247
+ /** 钩子兑现说明(未兑现时给出建议)。 */
248
+ hookNote: string
249
+ /** 本章结尾钩子强度 0-10。 */
250
+ endingHook: number
251
+ /** 剧情线推进情况(推进了哪条线/或未推进)。 */
252
+ plotlineProgress: string
253
+ /** 结构化:本章推进的剧情线名称列表(与项目剧情线 name 精确匹配,复盘后自动关联章节)。 */
254
+ advancedLines?: string[]
255
+ /** 连续性检查(人物位置/时间/伤势/资源是否与上章衔接)。 */
256
+ continuity: string
257
+ /** 近期节奏趋势提示(拖沓/爽点密度等)。 */
258
+ trend: string
259
+ /** 复盘时间。 */
260
+ reviewedAt: string
261
+ }
262
+
263
+ /** One review finding. */
264
+ export interface ReviewIssue {
265
+ /** Severity: high = must fix, medium = should fix, low = suggestion. */
266
+ severity: 'high' | 'medium' | 'low'
267
+ /** What the problem is. */
268
+ item: string
269
+ /** Concrete suggestion for fixing it. */
270
+ suggestion: string
271
+ }
272
+
273
+ /** AI review report for one chapter. */
274
+ export interface ReviewReport {
275
+ /** Overall score 0-100. */
276
+ score: number
277
+ /** Pass threshold (config; 70 default). */
278
+ passed: boolean
279
+ /** One-line verdict. */
280
+ verdict: string
281
+ /** Individual findings. */
282
+ issues: ReviewIssue[]
283
+ /** When the review ran. */
284
+ reviewedAt: string
285
+ }
286
+
287
+ /** A volume of the book. */
288
+ export interface Volume {
289
+ /** 1-based volume number. */
290
+ no: number
291
+ /** Volume title. */
292
+ title: string
293
+ /** Volume positioning / summary. */
294
+ summary: string
295
+ /** First chapter number of this volume. */
296
+ chapterStart: number
297
+ /** Last chapter number (inclusive). */
298
+ chapterEnd: number
299
+ }
300
+
301
+ /** A character card from the story bible. */
302
+ export interface CharacterCard {
303
+ name: string
304
+ role: 'protagonist' | 'supporting' | 'antagonist' | 'other'
305
+ /** Personality / traits (short lines). */
306
+ traits: string[]
307
+ /** Goals and motivations. */
308
+ goals: string
309
+ /** Key relations to other characters. */
310
+ relations: string
311
+ /** 知情度:该角色已经知道的事实/秘密(未列出的信息该角色不知道)。 */
312
+ knowledge?: string[]
313
+ }
314
+
315
+ /** The structured story bible (worldbuilding extracted from the outline). */
316
+ export interface StoryBible {
317
+ /** Genre + tone tags. */
318
+ genre: string
319
+ /** Worldbuilding rules (power system, geography, factions...). */
320
+ worldRules: string[]
321
+ /** Character cards. */
322
+ characters: CharacterCard[]
323
+ /** Writing red lines (forbidden content / must-avoid tropes). */
324
+ redLines: string[]
325
+ /** Style guidance (pacing, pov, tone). */
326
+ style: string[]
327
+ /** When the bible was generated. */
328
+ generatedAt?: string
329
+ }
330
+
331
+ /** A planted/active/resolved foreshadowing thread. */
332
+ export interface Foreshadow {
333
+ /** Stable id. */
334
+ id: string
335
+ /** What the foreshadow is. */
336
+ description: string
337
+ /** Chapter where it was planted (undefined = planned). */
338
+ plantedChapter?: number
339
+ /** Chapter where it should be paid off. */
340
+ targetChapter?: number
341
+ /** Lifecycle state. */
342
+ status: 'planned' | 'planted' | 'progressing' | 'resolved' | 'abandoned'
343
+ /** Resolution note when resolved. */
344
+ resolvedNote?: string
345
+ }
346
+
347
+ /** 一条已确立的叙事事实(事实库/时间线,注入后续章节生成)。 */
348
+ export interface ChapterFact {
349
+ /** 来源章节号。 */
350
+ chapterNo: number
351
+ /** 事实文本(人物状态/境界资源/关系变化/伏笔落地等)。 */
352
+ text: string
353
+ }
354
+
355
+ /** 一条全书质检发现的问题(一致性矛盾,定位到章)。 */
356
+ export interface AuditIssue {
357
+ /** 问题所在章节号(无法定位时 0)。 */
358
+ chapterNo: number
359
+ severity: 'high' | 'medium' | 'low'
360
+ /** 矛盾描述。 */
361
+ item: string
362
+ /** 修改建议。 */
363
+ suggestion: string
364
+ }
365
+
366
+ /** POST /audit 响应。 */
367
+ export interface AuditResponse {
368
+ issues: AuditIssue[]
369
+ /** 参与质检的章节数。 */
370
+ auditedChapters: number
371
+ /** 质检时间。 */
372
+ auditedAt: string
373
+ }
374
+
375
+ /** 全书质检的实时状态(通过 /status 暴露给面板/外部读取)。 */
376
+ export interface AuditStatus {
377
+ status: 'idle' | 'running' | 'done' | 'error'
378
+ /** 开始时间(ISO)。 */
379
+ startedAt?: string
380
+ /** 结束时间(ISO)。 */
381
+ finishedAt?: string
382
+ /** 总批次数(0 = 尚未开始/无章节)。 */
383
+ totalBatches: number
384
+ /** 已完成批次数。 */
385
+ completedBatches: number
386
+ /** 参与质检的章节数。 */
387
+ auditedChapters?: number
388
+ /** 发现的问题数(done 后有效)。 */
389
+ issuesCount?: number
390
+ /** 最近一次质检的问题清单(done 后有效;error 时为空)。 */
391
+ issues?: AuditIssue[]
392
+ /** 失败信息(error 时有效)。 */
393
+ error?: string
394
+ }
395
+
396
+ /** 一条剧情线(主线/支线/人物线/悬念线)。 */
397
+ export interface Plotline {
398
+ /** 稳定 id。 */
399
+ id: string
400
+ /** 线名。 */
401
+ name: string
402
+ /** 类型:主线 / 支线 / 人物线 / 悬念线。 */
403
+ kind: 'main' | 'branch' | 'character' | 'mystery'
404
+ /** 目标/终点(这条线最终要完成什么)。 */
405
+ goal: string
406
+ /** 当前进度说明(最近推进到哪)。 */
407
+ progress: string
408
+ /** 生命周期状态。 */
409
+ status: 'active' | 'paused' | 'resolved' | 'abandoned'
410
+ /** 关联章节号(推进/落地的章节)。 */
411
+ chapters: number[]
412
+ /** 创建时间。 */
413
+ createdAt: string
414
+ }
415
+
416
+ /** POST /plotlines 请求:剧情线增删改 + 关联章节 + AI 辅助。 */
417
+ export interface PlotlinesRequest {
418
+ op: 'add' | 'update' | 'remove' | 'link' | 'suggest' | 'refresh' | 'health' | 'plan'
419
+ /** add / update 时传入的完整剧情线。 */
420
+ line?: Plotline
421
+ /** remove / link / refresh 时的目标线 id。 */
422
+ id?: string
423
+ /** link 时关联的章节号。 */
424
+ chapterNo?: number
425
+ }
426
+
427
+ /** 剧情线健康检查报告。 */
428
+ export interface PlotlineHealthReport {
429
+ /** 是否需要新线(需要 / 暂不需要 / 再写 X 章后需要)。 */
430
+ verdict: string
431
+ /** 建议添加新线的时机说明。 */
432
+ timing: string
433
+ /** 依据(基于数据的理由,每条一句)。 */
434
+ reasons: string[]
435
+ /** 各线健康度。 */
436
+ lines: Array<{
437
+ name: string
438
+ /** ok=健康 / warning=预警 / stale=搁置过久。 */
439
+ health: 'ok' | 'warning' | 'stale'
440
+ note: string
441
+ }>
442
+ }
443
+
444
+ /** AI 剧情方案:下一阶段目标 + 建议新线。 */
445
+ export interface PlotlinePlan {
446
+ /** 下一阶段(未来 5-10 章)剧情方向。 */
447
+ direction: string
448
+ /** 建议的新线(可逐条采纳)。 */
449
+ suggestions: Plotline[]
450
+ }
451
+
452
+ /** POST /plotlines 响应。 */
453
+ export interface PlotlinesResponse {
454
+ plotlines: Plotline[]
455
+ /** op=suggest 时的 AI 建议候选线。 */
456
+ suggestions?: Plotline[]
457
+ /** op=health 时的健康检查报告。 */
458
+ health?: PlotlineHealthReport
459
+ /** op=plan 时的剧情方案。 */
460
+ plan?: PlotlinePlan
461
+ }
462
+
463
+ /** 一条敏感词命中。 */
464
+ export interface SensitiveHit {
465
+ /** 命中章节号(文本检测时为 0)。 */
466
+ chapterNo: number
467
+ /** 命中的违禁词。 */
468
+ word: string
469
+ /** 类别:政治 / 擦边 / 暴力 / 辱骂 / 广告 / 其他。 */
470
+ category: string
471
+ /** 出现次数。 */
472
+ count: number
473
+ }
474
+
475
+ /** POST /sensitive-check 请求:检测指定章节/任意文本/全书。 */
476
+ export interface SensitiveCheckRequest {
477
+ /** 检测该章正文。 */
478
+ chapterNo?: number
479
+ /** 检测任意文本(优先于 chapterNo)。 */
480
+ text?: string
481
+ /** 扫描全部已写章节。 */
482
+ all?: boolean
483
+ }
484
+
485
+ /** POST /sensitive-check 响应。 */
486
+ export interface SensitiveCheckResponse {
487
+ hits: SensitiveHit[]
488
+ /** 参与扫描的章节数。 */
489
+ scannedChapters: number
490
+ }
491
+
492
+ /** 开书想法 → AI 大纲方案(一个候选)。 */
493
+ export interface OutlineCandidate {
494
+ /** 唯一 id(前端暂留/换批用)。 */
495
+ id: string
496
+ /** 推荐书名。 */
497
+ bookName: string
498
+ /** 题材(如 仙侠修真 / 都市)。 */
499
+ genre: string
500
+ /** 核心卖点一句话。 */
501
+ sellingPoint: string
502
+ /** 完整大纲文本(可直接用作项目大纲,≥800 字)。 */
503
+ outline: string
504
+ }
505
+
506
+ /** POST /outline/suggest 请求:想法 → 2-3 个可选大纲。 */
507
+ export interface OutlineSuggestRequest {
508
+ /** 作者想法(一两句话,≥50 字)。 */
509
+ idea: string
510
+ /** 本次要生成的候选数(默认 3,最多 3)。 */
511
+ count?: number
512
+ /** 已暂留方案的剧情方向摘要(换批时让 LLM 避开,防止与已留方案重复)。 */
513
+ exclude?: string[]
514
+ }
515
+
516
+ /** POST /outline/suggest 响应。 */
517
+ export interface OutlineSuggestResponse {
518
+ candidates: OutlineCandidate[]
519
+ }
520
+
521
+ /** 拆书分析:一个分析小节。 */
522
+ export interface BreakdownSection {
523
+ /** 小节键:overview / plot / character / style / market。 */
524
+ key: string
525
+ /** 小节标题(如「拆书总览」)。 */
526
+ title: string
527
+ /** 可读分析稿(markdown)。 */
528
+ markdown: string
529
+ /** 结构化数据(程序可消费)。 */
530
+ structured: Record<string, unknown>
531
+ }
532
+
533
+ /** 拆书分析:一条证据(结论→原文回溯)。 */
534
+ export interface BreakdownEvidence {
535
+ label: string
536
+ excerpt: string
537
+ /** 来源章节号(0 = 未定位)。 */
538
+ chapterNo: number
539
+ /** 指向的结构化字段。 */
540
+ fieldKey?: string
541
+ }
542
+
543
+ /** POST /breakdown 请求:对已写章节做拆书分析。 */
544
+ export interface BreakdownRequest {
545
+ /** 分析范围:'recent'=最近 20 章 / 'volume:N'=第 N 卷 / 'all'=全书(默认 recent)。 */
546
+ scope?: string
547
+ /** 分析档位:'quick'=4 维(总览/剧情/人物/文风)/ 'standard'=5 维(+卖点)。 */
548
+ preset?: 'quick' | 'standard'
549
+ /** token 预算上限(默认 50000)。 */
550
+ budgetTokens?: number
551
+ }
552
+
553
+ /** POST /breakdown 响应。 */
554
+ export interface BreakdownResponse {
555
+ sections: BreakdownSection[]
556
+ evidence: BreakdownEvidence[]
557
+ /** 参与分析的章节数。 */
558
+ chaptersScanned: number
559
+ /** 估算消耗 token。 */
560
+ usedTokens: number
561
+ }
562
+
563
+ /** 角色卡:角色当前状态(从事实库聚合)。 */
564
+ export interface RoleStatusCard {
565
+ name: string
566
+ /** protagonist / supporting / antagonist / other。 */
567
+ role: string
568
+ /** 当前状态一句话(境界/资源/伤势/心境)。 */
569
+ status: string
570
+ /** 最近出场章节。 */
571
+ lastChapter: number
572
+ /** 出场次数。 */
573
+ appearances: number
574
+ }
575
+
576
+ /** 角色库条目(主表:作者维护 + AI 提炼 + 编年录自动聚合)。 */
577
+ export interface RoleRecord {
578
+ /** 角色名(唯一键)。 */
579
+ name: string
580
+ /** 定位:主角 / 女主 / 女配 / 配角 / 反派 / 路人。 */
581
+ roleLabel: 'protagonist' | 'female_lead' | 'female_support' | 'support' | 'antagonist' | 'extra'
582
+ /** 身份一句话(如:祭族后裔、青云宗杂役)。 */
583
+ identity: string
584
+ /** 性格标签。 */
585
+ traits: string[]
586
+ /** 目标与动机。 */
587
+ goals: string
588
+ /** 关系网:[角色名](关系)。 */
589
+ relations: string[]
590
+ /** 成长线:阶段 → 说明(可含章节)。 */
591
+ arc: string[]
592
+ /** 知情度:该角色已经知道的信息。 */
593
+ knowledge: string[]
594
+ /** 首次出场章节(编年录聚合,可手动修正)。 */
595
+ firstChapter?: number
596
+ /** 动漫形象描述词(AI 绘图用:中文描述 + 英文标签 + 关键外貌标签)。 */
597
+ imagePrompt?: {
598
+ /** 中文外貌描述:连贯一段(发色/瞳色/服装/气质/标志物)。 */
599
+ zh: string
600
+ /** 英文绘图标签:booru 风格逗号分隔。 */
601
+ en: string
602
+ /** 中文关键标签(发色/瞳色/服装/气质/标志物)。 */
603
+ tags: string[]
604
+ /** 依据来源说明(哪几章哪些描写)。 */
605
+ source?: string
606
+ }
607
+ /** 角色参考图(dataURL 或 URL)。用于漫画/漫剧出图时锁定角色一致性。 */
608
+ imageUrl?: string
609
+ /** 角色图集(图像锚点):立绘/四视图/表情/场景/细节等,label 标注用途。 */
610
+ gallery?: RoleImage[]
611
+ /** 该角色所需的情绪表情清单(提炼时 LLM 补全 6-12 个,如"疲惫/麻木/压抑悲伤")。 */
612
+ expressions?: string[]
613
+ /** LLM 精修的四类生图提示词包(前端拼装版之外的高质量版,promptKit 接口生成)。 */
614
+ promptKit?: {
615
+ /** 立绘:全身/半身正视图。 */
616
+ portrait: { zh: string; en: string }
617
+ /** 四视图:正面/侧面/背面设定表。 */
618
+ sheet: { zh: string; en: string }
619
+ /** 表情:同一脸部锚换情绪,每表情一段。 */
620
+ expressions: { name: string; zh: string; en: string }[]
621
+ /** 细节:标志物局部特写。 */
622
+ details: { zh: string; en: string }
623
+ }
624
+ /** 漫画/漫剧重要性:main=必须建卡保证一致;support=有锚点即可;extra=路人随机生成不约束。 */
625
+ importance?: 'main' | 'support' | 'extra'
626
+ }
627
+
628
+ /** 角色图集条目:一张已定型的角色图(图像锚点)。 */
629
+ export interface RoleImage {
630
+ /** 用途标签:立绘 / 四视图 / 表情-疲惫 / 场景 / 细节 等。 */
631
+ label: string
632
+ /** dataURL 或 URL。 */
633
+ dataUrl: string
634
+ }
635
+
636
+ /** 场景库条目:从正文提炼的「镜头场景」视觉锚点(漫剧分镜/生图用)。 */
637
+ export interface SceneCard {
638
+ /** 场景名(唯一键),如「旧茶渡·地下石殿」。 */
639
+ name: string
640
+ /** 一句话定位:空间/氛围/功能。 */
641
+ summary: string
642
+ /** 幕归属:第一幕·后场 / 第二幕·卖场 / …(便于按剧情段落组织)。 */
643
+ act?: string
644
+ /** 时间光态:夜间闭店后 / 雨夜 / 凌晨 / 频闪灯… */
645
+ moment?: string
646
+ /** 关键情节镜头 1-3 条:该场景拍什么(人物动作+情绪+镜头推进)。 */
647
+ beats?: string[]
648
+ /** 人物在场状态:主角/关键角色在该场景的状态一句话。 */
649
+ characterState?: string
650
+ /** 环境构成:空间结构/陈设/标志物。 */
651
+ elements: string[]
652
+ /** 色调与光影(含 HEX 色板,可空)。 */
653
+ palette: string[]
654
+ /** 氛围关键词:压抑/神秘/空旷… */
655
+ moods: string[]
656
+ /** 中文生图提示词(连贯一段,写实电影感)。 */
657
+ zh: string
658
+ /** 英文生图提示词(逗号分隔标签)。 */
659
+ en: string
660
+ /** 关键标签。 */
661
+ tags: string[]
662
+ /** 依据来源(哪几章哪些描写)。 */
663
+ source?: string
664
+ /** 场景图集(图像锚点):全景/局部/氛围 等。 */
665
+ gallery?: RoleImage[]
666
+ }
667
+
668
+ /** POST /scenes 请求:场景库提炼 / 采纳 / 更新 / 删除 / 图集。 */
669
+ export interface ScenesRequest {
670
+ op: 'extract' | 'adopt' | 'update' | 'remove' | 'image' | 'removeImage'
671
+ /** adopt / update 时传入的场景卡(adopt 可修改后采纳)。 */
672
+ scene?: SceneCard
673
+ /** remove / image 时的场景名。 */
674
+ name?: string
675
+ /** op='image' 时的图片 dataURL 与用途标签(全景/局部/氛围)。 */
676
+ dataUrl?: string
677
+ label?: string
678
+ }
679
+
680
+ /** POST /visual-rules 请求:视觉世界观规则提炼 / 保存。 */
681
+ export interface VisualRulesRequest {
682
+ op: 'extract' | 'save'
683
+ /** op=save 时的规则数组。 */
684
+ rules?: string[]
685
+ }
686
+
687
+ /** POST /visual-rules 响应。 */
688
+ export interface VisualRulesResponse {
689
+ rules: string[]
690
+ }
691
+
692
+ /** POST /scenes 响应。 */
693
+ export interface ScenesResponse {
694
+ scenes: SceneCard[]
695
+ /** op=extract 时的 AI 候选场景。 */
696
+ candidates?: SceneCard[]
697
+ }
698
+
699
+ /** POST /roles 请求:角色库增删改 + AI 提炼 + 参考图上传。 */
700
+ export interface RolesRequest {
701
+ op: 'extract' | 'adopt' | 'update' | 'remove' | 'visual' | 'image' | 'removeImage' | 'imageGenerate' | 'promptKit'
702
+ /** adopt / update 时传入的角色(adopt 可修改后采纳)。 */
703
+ role?: RoleRecord
704
+ /** remove 时的角色名。 */
705
+ name?: string
706
+ /** op='image' 时的参考图 dataURL。 */
707
+ dataUrl?: string
708
+ /** op='image' 时的图集用途标签(立绘/四视图/表情-x/场景/细节);缺省视为角色参考图(imageUrl)。 */
709
+ label?: string
710
+ /** op='imageGenerate' 时的漫画风格预设 id(用于统一角色图与漫画页风格)。 */
711
+ style?: string
712
+ }
713
+
714
+ /** POST /roles 响应。 */
715
+ export interface RolesResponse {
716
+ roles: RoleRecord[]
717
+ /** op=extract 时的 AI 候选角色。 */
718
+ candidates?: RoleRecord[]
719
+ /** op=visual 时的动漫形象描述词(已写入角色卡)。 */
720
+ visual?: RoleRecord['imagePrompt']
721
+ /** op=promptKit 时的四类提示词精修包(已写入角色卡)。 */
722
+ promptKit?: RoleRecord['promptKit']
723
+ /** op=image 时的角色参考图 dataURL。 */
724
+ imageUrl?: string
725
+ }
726
+
727
+ /** POST /bible/patch 请求:局部修补设定圣经。 */
728
+ export interface BiblePatchRequest {
729
+ worldRules?: string[]
730
+ redLines?: string[]
731
+ style?: string[]
732
+ /** 角色卡整体替换(人物志编辑知情度等)。 */
733
+ characters?: CharacterCard[]
734
+ }
735
+
736
+ /** POST /blurb 请求:AI 生成/补全或手动保存小说简介。 */
737
+ export interface BlurbRequest {
738
+ action: 'generate' | 'save'
739
+ /** 已写好的开头(AI 补全时使用;留空 = 全量生成)。 */
740
+ partial?: string
741
+ /** 手动保存的完整简介(action=save 时)。 */
742
+ text?: string
743
+ }
744
+
745
+ /** POST /chapter/check|save 请求:审查/保存手动编辑的正文。 */
746
+ export interface ChapterTextRequest {
747
+ chapterNo: number
748
+ /** 当前编辑中的正文全文。 */
749
+ text: string
750
+ /** 保存时携带:已在工作区审查过的报告(沿用落盘,不重复审);缺省则保存后自动正式审稿一次。 */
751
+ report?: ReviewReport
752
+ /** 审查/验证时携带:上一轮审稿报告。传入后进入「验证模式」——逐条核对原意见是否解决、
753
+ * 只挑新增 high,不再全新找茬(防止"越修 high 越多")。 */
754
+ previousReport?: ReviewReport
755
+ }
756
+
757
+ /** POST /chapter/save 响应。 */
758
+ export interface ChapterSaveResponse {
759
+ ok: boolean
760
+ chars: number
761
+ file: string
762
+ /** 落盘的审稿报告(沿用工作区报告或保存后自动审稿)。 */
763
+ report?: ReviewReport
764
+ }
765
+
766
+ /** POST /cover 请求:上传或移除封面。 */
767
+ export interface CoverRequest {
768
+ action: 'upload' | 'remove'
769
+ /** 上传时:data:image/...;base64,... 格式的图片数据。 */
770
+ dataUrl?: string
771
+ }
772
+
773
+ /** POST /rename 请求:重命名当前书。 */
774
+ export interface RenameRequest {
775
+ bookName: string
776
+ }
777
+
778
+ /** 大世界:一个境界等级。 */
779
+ export interface WorldRealm {
780
+ /** 境界名(练气/筑基/金丹…)。 */
781
+ name: string
782
+ /** 描述:突破条件/寿命/标志等。 */
783
+ description: string
784
+ }
785
+
786
+ /** 大世界:一个地理区域。 */
787
+ export interface WorldRegion {
788
+ name: string
789
+ description: string
790
+ /** 关联势力名(可空)。 */
791
+ faction?: string
792
+ }
793
+
794
+ /** 大世界:一方势力。 */
795
+ export interface WorldFaction {
796
+ name: string
797
+ /** 类型:宗门/家族/王朝/组织… */
798
+ kind: string
799
+ description: string
800
+ /** 驻地区域(可空)。 */
801
+ region?: string
802
+ }
803
+
804
+ /** 大世界结构化数据。 */
805
+ export interface WorldState {
806
+ realms: WorldRealm[]
807
+ regions: WorldRegion[]
808
+ factions: WorldFaction[]
809
+ }
810
+
811
+ /** POST /world 请求:AI 提炼或手动保存。 */
812
+ export interface WorldRequest {
813
+ action: 'generate' | 'save'
814
+ /** action=save 时的完整世界数据。 */
815
+ world?: WorldState
816
+ }
817
+
818
+ /** GET /cover 响应:封面的 dataUrl(无封面为 null)。 */
819
+ export interface CoverResponse {
820
+ dataUrl: string | null
821
+ }
822
+
823
+ /** The persisted project: outline + bible + plan + progress. */
824
+ export interface ProjectState {
825
+ /** Book title (first non-empty line of the outline, usually). */
826
+ bookName: string
827
+ /** Full outline text (docx-extracted or pasted). */
828
+ outline: string
829
+ /** Source outline path when loaded from a docx. */
830
+ outlinePath?: string
831
+ /** Structured story bible (worldbuilding), if generated. */
832
+ bible?: StoryBible
833
+ /** Volumes, if planned. */
834
+ volumes?: Volume[]
835
+ /** Chapter plan. */
836
+ chapters: ChapterPlan[]
837
+ /** Foreshadowing threads. */
838
+ foreshadows: Foreshadow[]
839
+ /** 写作资产(题材基底/推进模式/反AI规则/写法资产)。 */
840
+ assets?: ProjectAssets
841
+ /** 事实库/时间线:每章生成后抽取,注入后续章节保持一致性。 */
842
+ facts?: ChapterFact[]
843
+ /** 小说简介(面向读者的作品门面,AI 生成或手动保存)。 */
844
+ blurb?: string
845
+ /** 封面文件名(相对输出目录,如 cover.png)。 */
846
+ coverPath?: string
847
+ /** 大世界结构化数据(境界体系/区域/势力)。 */
848
+ world?: WorldState
849
+ /** 剧情线(主线/支线/人物线/悬念线)。 */
850
+ plotlines?: Plotline[]
851
+ /** 角色库(作者维护 + AI 提炼的主表)。 */
852
+ roles?: RoleRecord[]
853
+ /** 场景库(作者维护 + AI 提炼的主表)。 */
854
+ scenes?: SceneCard[]
855
+ /** 视觉世界观规则(生图/生视频必须遵守,从道藏提炼,注入所有提示词)。 */
856
+ visualRules?: string[]
857
+ /** 人物志:角色当前状态聚合结果(从编年录刷新后存档,打开页面直接显示)。 */
858
+ roleStatus?: RoleStatusCard[]
859
+ /** 漫剧分镜结果缓存:章号 → 分镜(持久化,刷新不丢)。 */
860
+ /** 漫剧分集计划缓存:卷号/0=全书 → 分集计划(持久化,刷新不丢)。 */
861
+ /** 漫画脚本缓存:章号 → 漫画脚本(持久化,刷新不丢)。 */
862
+ /** ISO timestamps. */
863
+ createdAt: string
864
+ updatedAt: string
865
+ }
866
+
867
+ /** Runtime config surface exposed to the panel (subset of plugin Config). */
868
+ export interface NovelConfig {
869
+ /** Absolute path of the default docx outline to load. */
870
+ outlinePath: string
871
+ /** Absolute output directory for chapters + project state. */
872
+ outputDir: string
873
+ /** LLM provider route (e.g. deepseek-official). */
874
+ provider: string
875
+ /** LLM model id (e.g. deepseek-v4-flash). */
876
+ model: string
877
+ /** LLM reasoning effort: off = no thinking; low/high/max = thinking intensity. */
878
+ reasoningEffort: 'off' | 'low' | 'high' | 'max'
879
+ /** 分析类任务(提炼/拆书/反推大纲等)的推理档位;默认 low,不受上面写作档位影响。 */
880
+ analysisReasoning: 'off' | 'low' | 'high' | 'max'
881
+ /** Target characters per chapter. */
882
+ chapterChars: number
883
+ /** Max output tokens per chapter call. */
884
+ maxTokens: number
885
+ /** Review pass threshold (0-100). */
886
+ reviewPassScore: number
887
+ /** Whether generation auto-runs review after writing. */
888
+ autoReview: boolean
889
+ /** Whether generation auto-runs the author review (hook/continuity/trend) after writing. */
890
+ autoAuthorReview: boolean
891
+ /** 修订/润色产出草稿后是否自动附带一次 AI 审查(工作区显示新稿评分与剩余问题)。 */
892
+ autoReviewAfterRevise: boolean
893
+ /** 豆包/Seedream 生图 API Key(保存在服务端配置,不暴露给前端明文回显)。 */
894
+ imageApiKey?: string
895
+ /** 豆包/Seedream 生图模型 ID(如 doubao-seedream-5-0-pro-260628)。 */
896
+ imageApiModel?: string
897
+ /** 是否启用豆包生图(默认关,避免误调用付费 API)。 */
898
+ imageApiEnabled?: boolean
899
+ }
900
+
901
+ /** GET /status response. */
902
+ export interface StatusResponse {
903
+ config: NovelConfig
904
+ /** The persisted project, when one exists in the output dir. */
905
+ project?: ProjectState
906
+ /** Chapter files already on disk (basenames, sorted). */
907
+ generatedFiles: string[]
908
+ /** 全书质检实时状态(用于面板/外部读取进度)。 */
909
+ audit?: AuditStatus
910
+ }
911
+
912
+ /** 生产单状态(生产单 = 区间批量生产执行器:计划补足 + 逐章生成 + 被拒分级处理)。 */
913
+ export interface RunState {
914
+ runId: string
915
+ /** 区间起点(含)。 */
916
+ startNo: number
917
+ /** 区间终点(含)。 */
918
+ endNo: number
919
+ status: 'running' | 'paused' | 'done' | 'stopped' | 'error'
920
+ /** 当前处理到的章号(已 approved 的章会快进)。 */
921
+ currentNo: number
922
+ stats: {
923
+ /** 新生成(含审稿)的章数。 */
924
+ generated: number
925
+ /** 被拒后按意见修订并通过的章数。 */
926
+ revised: number
927
+ /** 被拒后豁免通过(无 high)的章数。 */
928
+ exempted: number
929
+ /** error 后重新生成的章数。 */
930
+ regenerated: number
931
+ /** 生成失败的章数。 */
932
+ error: number
933
+ }
934
+ /** 两轮修订仍不过、保留草稿待人工的章号。 */
935
+ pendingManual: number[]
936
+ /** 运行日志(保留最近 300 条)。 */
937
+ log: Array<{ at: string; text: string }>
938
+ startedAt: string
939
+ updatedAt: string
940
+ error?: string
941
+ }
942
+
943
+ /** POST /run/start request. */
944
+ export interface RunStartRequest {
945
+ /** 起始章号(默认 1)。 */
946
+ startNo?: number
947
+ /** 结束章号(含;超出计划时自动补计划)。 */
948
+ endNo?: number
949
+ /** 或指定新增章数(从当前最后一章 +1 起)。 */
950
+ count?: number
951
+ }
952
+
953
+ /** POST /run/control request. */
954
+ export interface RunControlRequest {
955
+ action: 'pause' | 'resume' | 'stop'
956
+ }
957
+
958
+ /** POST /load-outline request: either a docx path or raw text. */
959
+ export interface LoadOutlineRequest {
960
+ /** Absolute docx path; defaults to the configured outline path. */
961
+ path?: string
962
+ /** Raw outline text (takes precedence over path when present). */
963
+ text?: string
964
+ }
965
+
966
+ /** POST /load-outline response. */
967
+ export interface LoadOutlineResponse {
968
+ outline: string
969
+ bookName: string
970
+ chars: number
971
+ path?: string
972
+ }
973
+
974
+ /** POST /plan request. */
975
+ export interface PlanRequest {
976
+ /** Outline to plan from; defaults to the persisted project's outline. */
977
+ outline?: string
978
+ /** Number of chapters to plan (default: 30). */
979
+ chapterCount?: number
980
+ /** Volume to plan (1-based); when given, plans only that volume's chapters. */
981
+ volume?: number
982
+ }
983
+
984
+ /** POST /plan response. */
985
+ export interface PlanResponse {
986
+ chapters: ChapterPlan[]
987
+ volumes?: Volume[]
988
+ }
989
+
990
+ /** POST /volumes request/response. */
991
+ export interface VolumesRequest {
992
+ /** Outline to split into volumes; defaults to the project outline. */
993
+ outline?: string
994
+ }
995
+ export interface VolumesResponse {
996
+ volumes: Volume[]
997
+ }
998
+
999
+ /** POST /bible request/response. */
1000
+ export interface BibleRequest {
1001
+ /** Outline to extract from; defaults to the project outline. */
1002
+ outline?: string
1003
+ }
1004
+ export interface BibleResponse {
1005
+ bible: StoryBible
1006
+ }
1007
+
1008
+ /** POST /generate request: one chapter of the current project. */
1009
+ export interface GenerateRequest {
1010
+ chapterNo: number
1011
+ /** When true, skips the auto-review step. */
1012
+ skipReview?: boolean
1013
+ }
1014
+
1015
+ /** One NDJSON frame of a generation/review/rewrite stream. */
1016
+ export type JobFrame =
1017
+ | { type: 'start'; no: number; title: string }
1018
+ | { type: 'delta'; text: string }
1019
+ | { type: 'progress'; chars: number }
1020
+ | { type: 'done'; no: number; file: string; chars: number; title: string }
1021
+ | { type: 'review'; no: number; report: ReviewReport }
1022
+ | { type: 'author-review'; no: number; review: AuthorReview }
1023
+ | { type: 'author-backfill-done'; count: number }
1024
+ | { type: 'rewritten'; no: number; file: string; chars: number }
1025
+ /** 润色/重写完成,产物作为待确认草稿(尚未覆盖正文)。 */
1026
+ | { type: 'drafted'; no: number; chars: number; draft: string }
1027
+ | { type: 'outline-progress'; done: number; total: number; phase: string }
1028
+ | { type: 'outline-done'; outline: string; chars: number }
1029
+ | { type: 'error'; no: number; message: string }
1030
+
1031
+ /** POST /review request: review one written chapter. */
1032
+ export interface ReviewRequest {
1033
+ chapterNo: number
1034
+ }
1035
+
1036
+ /** POST /rewrite request: rewrite one chapter (optionally per review issues). */
1037
+ export interface RewriteRequest {
1038
+ chapterNo: number
1039
+ /** Free-form instructions; defaults to fixing the review's high issues. */
1040
+ instructions?: string
1041
+ /**
1042
+ * 局部修订:正文中的一段原文(无需完全精确,取一个自然段内的片段即可)。
1043
+ * 提供时只重写该段,其余正文保持不变;不提供时整章重写。
1044
+ */
1045
+ target?: string
1046
+ }
1047
+
1048
+ /** POST /polish request: de-AI-ify one chapter. */
1049
+ export interface PolishRequest {
1050
+ chapterNo: number
1051
+ }
1052
+
1053
+ /** POST /draft/apply | /draft/discard request: 采纳或放弃待确认草稿。 */
1054
+ export interface DraftDecisionRequest {
1055
+ chapterNo: number
1056
+ /** apply 时可携带审查报告(沿用结论定状态;不携带则置 written)。 */
1057
+ report?: ReviewReport
1058
+ }
1059
+
1060
+ /** POST /summary request: (re)generate a chapter summary. */
1061
+ export interface SummaryRequest {
1062
+ chapterNo: number
1063
+ }
1064
+
1065
+ /** POST /foreshadow request: create, update, or AI-suggest foreshadows. */
1066
+ export interface ForeshadowRequest {
1067
+ /** When true, runs the LLM suggestion pass (ignores other fields). */
1068
+ suggest?: boolean
1069
+ /** When given, updates that foreshadow instead of creating one. */
1070
+ id?: string
1071
+ description?: string
1072
+ plantedChapter?: number
1073
+ targetChapter?: number
1074
+ status?: Foreshadow['status']
1075
+ resolvedNote?: string
1076
+ }
1077
+ export interface ForeshadowResponse {
1078
+ foreshadows: Foreshadow[]
1079
+ }
1080
+
1081
+ /** GET /chapter response. */
1082
+ export interface ChapterResponse {
1083
+ no: number
1084
+ title: string
1085
+ markdown: string
1086
+ }
1087
+
1088
+ /** POST /export request/response. */
1089
+ export interface ExportRequest {
1090
+ format: 'txt' | 'md'
1091
+ }
1092
+ export interface ExportResponse {
1093
+ file: string
1094
+ chars: number
1095
+ chapters: number
1096
+ }
1097
+
1098
+ /** POST /config request: patch any subset of the runtime config. */
1099
+ export interface ConfigPatch {
1100
+ outlinePath?: string
1101
+ outputDir?: string
1102
+ provider?: string
1103
+ model?: string
1104
+ reasoningEffort?: 'off' | 'low' | 'high' | 'max'
1105
+ analysisReasoning?: 'off' | 'low' | 'high' | 'max'
1106
+ chapterChars?: number
1107
+ maxTokens?: number
1108
+ reviewPassScore?: number
1109
+ autoReview?: boolean
1110
+ autoAuthorReview?: boolean
1111
+ autoReviewAfterRevise?: boolean
1112
+ imageApiKey?: string
1113
+ imageApiModel?: string
1114
+ imageApiEnabled?: boolean
1115
+ }
1116
+
1117
+ // ------------------------------------------------------------ assistant
1118
+
1119
+ /** One assistant conversation message (persisted per project). */
1120
+ export interface AssistantMessage {
1121
+ role: 'user' | 'assistant' | 'tool'
1122
+ /** Message text (tool messages carry the tool result). */
1123
+ content: string
1124
+ /** ISO timestamp. */
1125
+ ts: string
1126
+ /** For tool messages: which tool ran. */
1127
+ tool?: string
1128
+ }
1129
+
1130
+ /** POST /assistant request: one user turn. */
1131
+ export interface AssistantRequest {
1132
+ message: string
1133
+ }
1134
+
1135
+ /** One NDJSON frame of the assistant stream. */
1136
+ export type AssistantFrame =
1137
+ | { type: 'delta'; text: string }
1138
+ | { type: 'tool'; name: string; status: 'start' | 'done' | 'error'; detail?: string }
1139
+ /** Live output while a tool runs (e.g. chapter text being generated). */
1140
+ | { type: 'toolDelta'; name: string; text: string }
1141
+ | { type: 'done' }
1142
+ | { type: 'error'; message: string }
1143
+
1144
+ /** GET /assistant-history response. */
1145
+ export interface AssistantHistoryResponse {
1146
+ messages: AssistantMessage[]
1147
+ }
1148
+
1149
+ // ---------------------------------------------------------- writing assets
1150
+
1151
+ /** 题材基底库:一本书属于哪个阅读市场。树形(题材→子题材→下级)。 */
1152
+ export interface GenreNode {
1153
+ /** 题材名称(标签,如「仙侠修真」「都市异能」)。 */
1154
+ name: string
1155
+ /** 题材特征、常见爽点、叙事重心或读者期待。 */
1156
+ description: string
1157
+ /** 子题材。 */
1158
+ children: GenreNode[]
1159
+ }
1160
+
1161
+ /** 推进模式库:读者为什么继续看下一章。 */
1162
+ export interface ProgressionMode {
1163
+ /** 模式名称(如「升级变强」「经营扩张」「解谜揭露」)。 */
1164
+ name: string
1165
+ /** 核心驱动力:靠什么制造追读动力。 */
1166
+ driver: string
1167
+ /** 读者期待:每隔几章获得什么变化或回报。 */
1168
+ readerExpectation: string
1169
+ /** 常见兑现方式(爽点如何落地)。 */
1170
+ payoffs: string[]
1171
+ /** 节奏风险:最怕什么(重复升级、冲突变弱、谜题拖太久…)。 */
1172
+ risks: string[]
1173
+ /** 主模式或辅助模式。 */
1174
+ primary: boolean
1175
+ }
1176
+
1177
+ /** 反 AI 规则:一条「要避免的问题 + 修正方向」。 */
1178
+ export interface AntiAiRule {
1179
+ /** 规则名(如「禁止解释型心理描写」「AI 高频套话」)。 */
1180
+ name: string
1181
+ /** 要避免的表达问题,具体可检查。 */
1182
+ avoid: string
1183
+ /** 推荐修正方向。 */
1184
+ fix: string
1185
+ /** 命中即告警的具体表达模式(用于审稿逐条核对与去 AI 味检测)。 */
1186
+ detectPatterns?: string[]
1187
+ /** 是否内置全局规则(内置规则随插件发布,项目规则为用户自定义)。 */
1188
+ builtin?: boolean
1189
+ }
1190
+
1191
+ /** 预置写法模板(来自 AI-Novel-Writing-Assistant 内置数据,一键绑定无需样本文本)。 */
1192
+ export interface StyleTemplate {
1193
+ /** 模板 key(如 power-up-escalation)。 */
1194
+ key: string
1195
+ /** 模板名(如「爽文递进推进流」)。 */
1196
+ name: string
1197
+ /** 模板说明。 */
1198
+ description: string
1199
+ /** 分类(如「爽文流」「悬疑流」)。 */
1200
+ category: string
1201
+ /** 适用题材。 */
1202
+ applicableGenres: string[]
1203
+ /** 叙述规则。 */
1204
+ proseRules: string[]
1205
+ /** 角色/台词规则。 */
1206
+ dialogueRules: string[]
1207
+ /** 语言规则。 */
1208
+ languageRules: string[]
1209
+ /** 节奏规则。 */
1210
+ rhythmRules: string[]
1211
+ /** 该模板默认绑定的反 AI 规则 key(内置规则名)。 */
1212
+ defaultAntiAiRuleKeys: string[]
1213
+ }
1214
+
1215
+ /** 写法引擎:从样本文本提取的叙事风格资产。 */
1216
+ export interface StyleAsset {
1217
+ /** 资产名(如「林越式痞坏」「冷峻猎手风」)。 */
1218
+ name: string
1219
+ /** 叙述视角与句式节奏。 */
1220
+ proseRules: string[]
1221
+ /** 角色台词风格。 */
1222
+ dialogueRules: string[]
1223
+ /** 描写密度与情绪表达。 */
1224
+ descriptionRules: string[]
1225
+ /** 表达边界(不要做什么)。 */
1226
+ boundaries: string[]
1227
+ /** 来源样本文本(可空)。 */
1228
+ sourceText?: string
1229
+ /** 创建时间。 */
1230
+ createdAt: string
1231
+ }
1232
+
1233
+ /** 项目写作资产(题材基底 + 推进模式 + 反 AI 规则 + 写法资产)。 */
1234
+ export interface ProjectAssets {
1235
+ /** 本书选用的题材(可以是题材基底库中某节点名)。 */
1236
+ genre?: GenreNode
1237
+ /** 主推进模式。 */
1238
+ primaryProgression?: ProgressionMode
1239
+ /** 辅助推进模式。 */
1240
+ auxiliaryProgressions: ProgressionMode[]
1241
+ /** 生效的反 AI 规则(内置 + 自定义)。 */
1242
+ antiAiRules: AntiAiRule[]
1243
+ /** 绑定的写法资产。 */
1244
+ styleAssets: StyleAsset[]
1245
+ /** 资产更新时间。 */
1246
+ updatedAt?: string
1247
+ }
1248
+
1249
+ /** GET /assets response(含全局题材库与反 AI 规则库)。 */
1250
+ export interface AssetsResponse {
1251
+ projectAssets: ProjectAssets
1252
+ /** 全局题材基底库(可复用资产,跨书)。 */
1253
+ genreLibrary: GenreNode[]
1254
+ /** 全局反 AI 规则库(内置默认规则)。 */
1255
+ antiAiLibrary: AntiAiRule[]
1256
+ /** 预置写法模板(一键绑定,无需样本文本)。 */
1257
+ styleTemplates: StyleTemplate[]
1258
+ /** 内置推进模式候选。 */
1259
+ progressionLibrary: ProgressionMode[]
1260
+ }
1261
+
1262
+ /** POST /assets request:更新项目写作资产(部分字段可选)。 */
1263
+ export interface AssetsPatch {
1264
+ genre?: GenreNode
1265
+ primaryProgression?: ProgressionMode
1266
+ auxiliaryProgressions?: ProgressionMode[]
1267
+ antiAiRules?: AntiAiRule[]
1268
+ styleAssets?: StyleAsset[]
1269
+ }
1270
+
1271
+ /** POST /style-engine request:从样本文本提取写法资产。 */
1272
+ export interface StyleEngineRequest {
1273
+ /** 样本文本(风格来源)。 */
1274
+ sampleText: string
1275
+ /** 资产名(可选,默认「风格资产 N」)。 */
1276
+ name?: string
1277
+ }