@waterwx/dsh-novel-forge 1.3.1 → 1.3.2-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 (161) hide show
  1. package/README.md +288 -279
  2. package/lib/client.js +56309 -12221
  3. package/lib/index.js +14239 -5595
  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 +24 -9
  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 +186 -10
  11. package/lib/types/client/chip-prefs.d.ts +36 -0
  12. package/lib/types/client/docx.d.ts +2 -0
  13. package/lib/types/client/index.d.ts +1 -1
  14. package/lib/types/client/llmLive.d.ts +31 -0
  15. package/lib/types/client/locales.d.ts +28 -67
  16. package/lib/types/client/panel/AdaptModeView.d.ts +5 -0
  17. package/lib/types/client/panel/AiTag.d.ts +1 -0
  18. package/lib/types/client/panel/AssistantTab.d.ts +4 -1
  19. package/lib/types/client/panel/AuthorAssetsView.d.ts +4 -0
  20. package/lib/types/client/panel/AuthorHome.d.ts +34 -0
  21. package/lib/types/client/panel/BookAnalysisView.d.ts +4 -0
  22. package/lib/types/client/panel/CmdPalette.d.ts +12 -0
  23. package/lib/types/client/panel/CreateBookView.d.ts +5 -1
  24. package/lib/types/client/panel/DirectorView.d.ts +7 -0
  25. package/lib/types/client/panel/GlobalAssetLibraryView.d.ts +4 -0
  26. package/lib/types/client/panel/IdeaInspirationView.d.ts +6 -0
  27. package/lib/types/client/panel/ImportModal.d.ts +7 -0
  28. package/lib/types/client/panel/KnowledgeBaseView.d.ts +4 -0
  29. package/lib/types/client/panel/LiveFeedLog.d.ts +13 -0
  30. package/lib/types/client/panel/MarketRadarView.d.ts +5 -0
  31. package/lib/types/client/panel/ModelManager.d.ts +14 -0
  32. package/lib/types/client/panel/NovelPanel.d.ts +6 -1
  33. package/lib/types/client/panel/PageHeader.d.ts +18 -0
  34. package/lib/types/client/panel/ProgressConsole.d.ts +17 -0
  35. package/lib/types/client/panel/ProgressHomeView.d.ts +5 -0
  36. package/lib/types/client/panel/PromptSlotsView.d.ts +11 -0
  37. package/lib/types/client/panel/ReasoningSection.d.ts +10 -0
  38. package/lib/types/client/panel/SettingsView.d.ts +19 -0
  39. package/lib/types/client/panel/ShelfView.d.ts +12 -1
  40. package/lib/types/client/panel/SubPage.d.ts +27 -0
  41. package/lib/types/client/panel/TensionView.d.ts +18 -0
  42. package/lib/types/client/panel/TimelineView.d.ts +18 -0
  43. package/lib/types/client/panel/helpers.d.ts +5 -3
  44. package/lib/types/client/panel/toast.d.ts +2 -0
  45. package/lib/types/client/panel/views.d.ts +25 -7
  46. package/lib/types/client/run-status.d.ts +21 -0
  47. package/lib/types/client/text.d.ts +9 -0
  48. package/lib/types/docx-core.d.ts +16 -0
  49. package/lib/types/docx.d.ts +2 -3
  50. package/lib/types/engine.d.ts +186 -45
  51. package/lib/types/global-assets.d.ts +6 -0
  52. package/lib/types/index.d.ts +22 -8
  53. package/lib/types/llm-live.d.ts +75 -0
  54. package/lib/types/llm-retry.d.ts +38 -0
  55. package/lib/types/market-radar-scan.d.ts +19 -0
  56. package/lib/types/market-radar-sources.d.ts +31 -0
  57. package/lib/types/migrate-output.d.ts +25 -0
  58. package/lib/types/novel-context.d.ts +80 -0
  59. package/lib/types/prompt-slots.d.ts +57 -0
  60. package/lib/types/prompt-utils.d.ts +35 -0
  61. package/lib/types/prompting.d.ts +10 -0
  62. package/lib/types/protocol.d.ts +1362 -166
  63. package/lib/types/review-policy.d.ts +97 -0
  64. package/lib/types/revision.d.ts +76 -0
  65. package/lib/types/routes.d.ts +4 -0
  66. package/lib/types/run.d.ts +23 -1
  67. package/lib/types/snapshots.d.ts +46 -0
  68. package/lib/types/stage-contract.d.ts +60 -0
  69. package/lib/types/tension.d.ts +53 -0
  70. package/lib/types/timeline.d.ts +37 -0
  71. package/package.json +52 -28
  72. package/src/action-guard.ts +127 -0
  73. package/src/ai-scan.ts +179 -0
  74. package/src/assets.ts +1806 -520
  75. package/src/assistant.ts +1098 -770
  76. package/src/author-assets.ts +149 -0
  77. package/src/bookshelf.ts +187 -151
  78. package/src/client/api.ts +378 -21
  79. package/src/client/chip-prefs.ts +121 -0
  80. package/src/client/docx.ts +37 -69
  81. package/src/client/index.ts +3 -1
  82. package/src/client/llmLive.ts +111 -0
  83. package/src/client/locales.ts +28 -253
  84. package/src/client/mount.tsx +1 -1
  85. package/src/client/panel/AdaptModeView.tsx +535 -0
  86. package/src/client/panel/AiTag.tsx +7 -0
  87. package/src/client/panel/AssetsTab.tsx +448 -458
  88. package/src/client/panel/AssistantTab.tsx +355 -301
  89. package/src/client/panel/AuthorAssetsView.tsx +206 -0
  90. package/src/client/panel/AuthorHome.tsx +309 -0
  91. package/src/client/panel/BookAnalysisView.tsx +63 -0
  92. package/src/client/panel/CmdPalette.tsx +102 -0
  93. package/src/client/panel/CreateBookView.tsx +366 -348
  94. package/src/client/panel/DirectorView.tsx +200 -0
  95. package/src/client/panel/GlobalAssetLibraryView.tsx +168 -0
  96. package/src/client/panel/IdeaInspirationView.tsx +76 -0
  97. package/src/client/panel/ImportModal.tsx +303 -0
  98. package/src/client/panel/KnowledgeBaseView.tsx +125 -0
  99. package/src/client/panel/LiveFeedLog.tsx +204 -0
  100. package/src/client/panel/MarketRadarView.tsx +377 -0
  101. package/src/client/panel/ModelManager.tsx +205 -0
  102. package/src/client/panel/NovelPanel.tsx +3135 -2651
  103. package/src/client/panel/PageHeader.tsx +37 -0
  104. package/src/client/panel/ProgressConsole.tsx +63 -0
  105. package/src/client/panel/PromptSlotsView.tsx +97 -0
  106. package/src/client/panel/ReaderView.tsx +306 -306
  107. package/src/client/panel/ReasoningSection.tsx +31 -0
  108. package/src/client/panel/RunPanel.tsx +64 -32
  109. package/src/client/panel/SettingsView.tsx +354 -0
  110. package/src/client/panel/ShelfView.tsx +266 -236
  111. package/src/client/panel/SubPage.tsx +42 -0
  112. package/src/client/panel/TensionView.tsx +212 -0
  113. package/src/client/panel/TimelineView.tsx +208 -0
  114. package/src/client/panel/WorldTab.tsx +202 -202
  115. package/src/client/panel/helpers.ts +7 -5
  116. package/src/client/panel/panel.module.css +4481 -1655
  117. package/src/client/panel/toast.ts +51 -0
  118. package/src/client/panel/views.tsx +401 -314
  119. package/src/client/run-status.ts +171 -0
  120. package/src/client/sidebar-entry.ts +1 -1
  121. package/src/client/text.ts +28 -0
  122. package/src/docx-core.ts +53 -0
  123. package/src/docx.ts +44 -83
  124. package/src/engine.ts +4672 -2943
  125. package/src/global-assets.ts +59 -0
  126. package/src/index.ts +89 -33
  127. package/src/llm-live.ts +260 -0
  128. package/src/llm-retry.ts +77 -0
  129. package/src/market-radar-scan.ts +41 -0
  130. package/src/market-radar-sources.ts +173 -0
  131. package/src/migrate-output.ts +76 -0
  132. package/src/novel-context.ts +286 -0
  133. package/src/prompt-slots.ts +125 -0
  134. package/src/prompting.ts +26 -0
  135. package/src/protocol.ts +1388 -158
  136. package/src/review-policy.ts +161 -0
  137. package/src/revision.ts +283 -0
  138. package/src/routes.ts +1934 -434
  139. package/src/run.ts +118 -21
  140. package/src/snapshots.ts +174 -0
  141. package/src/stage-contract.ts +189 -0
  142. package/src/tension.ts +251 -0
  143. package/src/timeline.ts +159 -0
  144. package/lib/client.js.map +0 -1
  145. package/lib/index.js.map +0 -1
  146. package/lib/types/comic-presets.d.ts +0 -12
  147. package/scripts/assistant-frames.txt +0 -8
  148. package/scripts/diagnose-adapter.mts +0 -81
  149. package/scripts/diagnose-assistant.mjs +0 -58
  150. package/scripts/diagnose-bible.mjs +0 -72
  151. package/scripts/diagnose-harness.mts +0 -75
  152. package/scripts/novel-forge-restart.log +0 -10
  153. package/scripts/novel-forge-web.stderr.log +0 -2
  154. package/scripts/novel-forge-web.stdout.log +0 -1
  155. package/scripts/outline-sample.txt +0 -449
  156. package/scripts/probe.mjs +0 -6
  157. package/scripts/restart-web.ps1 +0 -88
  158. package/scripts/smoke.mts +0 -72
  159. package/scripts/upload-github.ps1 +0 -51
  160. package/src/client/panel/BookshelfBar.tsx +0 -170
  161. package/src/comic-presets.ts +0 -67
package/src/protocol.ts CHANGED
@@ -15,6 +15,34 @@ export const NOVEL_API = {
15
15
  bible: '/api/dsh-novel-forge/bible',
16
16
  assets: '/api/dsh-novel-forge/assets',
17
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
+ /** 查看某次调用实际发送的 Prompt(按 sessionId)。 */
28
+ llmPrompt: '/api/dsh-novel-forge/llm-live/prompt',
29
+ /** 清零本次运行的用量账本。 */
30
+ usageReset: '/api/dsh-novel-forge/usage/reset',
31
+ /** 章节历史版本(快照)。 */
32
+ snapshot: '/api/dsh-novel-forge/snapshot',
33
+ /** 修订指令合并(POST:汇总审稿/时间线/张力为一轮)。 */
34
+ revisionPlan: '/api/dsh-novel-forge/revision/plan',
35
+ /** 张力曲线(GET 数据 / POST 设置)。 */
36
+ tension: '/api/dsh-novel-forge/tension',
37
+ /** 提示词槽位(GET 列表 / POST 写入)。 */
38
+ promptSlots: '/api/dsh-novel-forge/prompt-slots',
39
+ /** 故事时间线(GET 列表 / POST 操作)。 */
40
+ timeline: '/api/dsh-novel-forge/timeline',
41
+ marketRadar: '/api/dsh-novel-forge/market-radar',
42
+ marketRadarScan: '/api/dsh-novel-forge/market-radar/scan',
43
+ marketRadarApply: '/api/dsh-novel-forge/market-radar/apply',
44
+ marketRadarSync: '/api/dsh-novel-forge/market-radar/foundation-sync',
45
+ marketRadarBrief: '/api/dsh-novel-forge/market-radar/brief',
18
46
  generate: '/api/dsh-novel-forge/generate',
19
47
  review: '/api/dsh-novel-forge/review',
20
48
  rewrite: '/api/dsh-novel-forge/rewrite',
@@ -36,6 +64,24 @@ export const NOVEL_API = {
36
64
  /** 清空助手对话记录。 */
37
65
  assistantClear: '/api/dsh-novel-forge/assistant/clear',
38
66
  bookshelf: '/api/dsh-novel-forge/bookshelf',
67
+ /** 导入已有项目目录(含 novel-project.json)到书架。 */
68
+ bookshelfImportDir: '/api/dsh-novel-forge/bookshelf/import-dir',
69
+ /** 导入 txt/md 全本:拆章建项目并登记书架。 */
70
+ bookshelfImportText: '/api/dsh-novel-forge/bookshelf/import-text',
71
+ /** 导入 txt/md 全本:拆章预览(不落盘)。 */
72
+ bookshelfImportTextPreview: '/api/dsh-novel-forge/bookshelf/import-text/preview',
73
+ /** LLM 模型连通性测试:真实最小调用,验证 Key / 端点 / 模型可用。 */
74
+ llmTest: '/api/dsh-novel-forge/llm-test',
75
+ /** 添加模型:厂商直填 key 或自定义路由,写进 DSH 凭据与 llm-pi-ai 路由。 */
76
+ addModel: '/api/dsh-novel-forge/llm-add',
77
+ /** 运行时厂商目录(DSH pi-ai 可配置提供方 + 内置适配器)。 */
78
+ llmVendors: '/api/dsh-novel-forge/llm-vendors',
79
+ /** 查询某个 provider 当前可用的模型(添加成功后可即时刷新)。 */
80
+ llmModels: '/api/dsh-novel-forge/llm-models',
81
+ /** 已注册的提供方路由列表(提供方管理)。 */
82
+ llmProviders: '/api/dsh-novel-forge/llm-providers',
83
+ /** 移除一个提供方。 */
84
+ llmRemove: '/api/dsh-novel-forge/llm-remove',
39
85
  /** 重置项目(可选携带新大纲):清空设定/卷/章节/伏笔/资产/事实库。 */
40
86
  reset: '/api/dsh-novel-forge/reset',
41
87
  /** 全书一致性质检:LLM 扫描已生成章节,输出矛盾问题清单。 */
@@ -44,22 +90,20 @@ export const NOVEL_API = {
44
90
  charactersRefresh: '/api/dsh-novel-forge/characters/refresh',
45
91
  /** 事实库回填:对历史已生成章节批量抽取事实(旧章节无事实记录时用)。 */
46
92
  factsBackfill: '/api/dsh-novel-forge/facts/backfill',
47
- /** 设定圣经局部修补(如世界观规则编辑)。 */
93
+ /** 道藏局部修补(如世界观规则编辑)。 */
48
94
  biblePatch: '/api/dsh-novel-forge/bible/patch',
49
95
  /** 小说简介:生成(AI)/补全(AI)/保存。 */
50
96
  blurb: '/api/dsh-novel-forge/blurb',
51
97
  /** 重命名当前书(同步项目与书架条目)。 */
52
98
  rename: '/api/dsh-novel-forge/rename',
53
- /** 大世界:AI 提炼 / 保存结构化数据(境界/区域/势力)。 */
99
+ /** 大世界:提炼 / 保存结构化数据(境界/区域/势力)。 */
54
100
  world: '/api/dsh-novel-forge/world',
55
101
  /** 封面:GET 读取(dataUrl)/ POST 上传或移除。 */
56
102
  cover: '/api/dsh-novel-forge/blurb/cover',
57
103
  /** 剧情线管理:增删改 + 关联章节。 */
58
104
  plotlines: '/api/dsh-novel-forge/plotlines',
59
- /** 角色库:AI 提炼 / 采纳 / 更新 / 删除。 */
105
+ /** 角色库:提炼 / 采纳 / 更新 / 删除。 */
60
106
  roles: '/api/dsh-novel-forge/roles',
61
- scenes: '/api/dsh-novel-forge/scenes',
62
- visualRules: '/api/dsh-novel-forge/visual-rules',
63
107
  /** 作者复盘补跑:对已写章节补齐 authorReview(全书流式 / 单章 JSON)。 */
64
108
  reviewBackfill: '/api/dsh-novel-forge/review/backfill',
65
109
  /** 章节复位:generating 卡死 → pending(可重新生成)。 */
@@ -68,13 +112,12 @@ export const NOVEL_API = {
68
112
  chapterApprove: '/api/dsh-novel-forge/chapter/approve',
69
113
  /** 敏感词检查:全书已写章节或指定文本。 */
70
114
  sensitiveCheck: '/api/dsh-novel-forge/sensitive-check',
71
- /** 开书想法 → AI 补全大纲:输入一句话想法,生成 2-3 个可选大纲方案。 */
115
+ /** 开书想法 → 补全大纲:输入一句话想法,生成 2-3 个可选大纲方案。 */
72
116
  outlineSuggest: '/api/dsh-novel-forge/outline/suggest',
117
+ /** 反推大纲:从已写章节正文反向生成全书总纲(NDJSON 流)。 */
118
+ outlineReverse: '/api/dsh-novel-forge/outline/reverse',
73
119
  /** 拆书分析:对已写章节做结构/人物/文风/卖点四维体检(两阶段:源笔记→分节分析)。 */
74
120
  breakdown: '/api/dsh-novel-forge/breakdown',
75
- /** 漫剧分镜生成:章节 → 角色锚点 + 分镜表(可适配豆包/Seedance/SD)。 */
76
- /** 漫剧分集计划:读一卷 → 按故事弧线分集(高潮拆集/过渡并章)。 */
77
- /** 漫画脚本:章节 → 分页分格漫画脚本(含角色视觉锚点)。 */
78
121
  /** 生产单:启动批量生产(计划补足 + 逐章生成 + 被拒分级处理)。 */
79
122
  runStart: '/api/dsh-novel-forge/run/start',
80
123
  /** 生产单控制:pause / resume / stop。 */
@@ -82,7 +125,39 @@ export const NOVEL_API = {
82
125
  /** 生产单状态(含进度统计与日志)。 */
83
126
  runStatus: '/api/dsh-novel-forge/run/status',
84
127
  config: '/api/dsh-novel-forge/config',
128
+ /** 输出目录迁移:dryRun 预览 / 确认后搬文件并联动配置与书架。 */
129
+ moveOutputDir: '/api/dsh-novel-forge/move-output-dir',
130
+ /** 本书参数:POST {} 读取;POST {patch} 合并保存(存 novel-project.json)。 */
131
+ bookSettings: '/api/dsh-novel-forge/book-settings',
85
132
  openFolder: '/api/dsh-novel-forge/open-folder',
133
+ /** 插件自更新:在 DSH profile 目录拉取最新 npm 版(下载后需重启 DSH 生效)。 */
134
+ pluginUpdate: '/api/dsh-novel-forge/plugin/update',
135
+ /** 作者资产库/总数据:读取个人跨书资产(笔法/红线/套路/角色模板/世界观模板)。 */
136
+ authorAssets: '/api/dsh-novel-forge/author-assets',
137
+ /** 作者资产库:新增/更新一条资产(upsert by id)。 */
138
+ authorAssetsUpsert: '/api/dsh-novel-forge/author-assets/upsert',
139
+ /** 作者资产库:删除一条资产。 */
140
+ authorAssetsRemove: '/api/dsh-novel-forge/author-assets/remove',
141
+ /** 作者资产库:导入默认(书架书的写作资产/角色 + 内置全局库)批量沉淀。 */
142
+ authorAssetsImportDefault: '/api/dsh-novel-forge/author-assets/import-default',
143
+ /** 改编模式:上传全文 → 分析 → 原文设定卡片/可改范围矩阵。 */
144
+ adaptAnalyze: '/api/dsh-novel-forge/adapt/analyze',
145
+ /** 改编模式:确认要改的维度 → 生成映射表/改编规则/联动影响清单。 */
146
+ adaptPropose: '/api/dsh-novel-forge/adapt/propose',
147
+ /** 改编模式:执行术语替换(全局替换 + 命中统计 + 改编文本预览)。 */
148
+ adaptExecute: '/api/dsh-novel-forge/adapt/execute',
149
+ /** 改编模式:保存改编全文为新书(原书保留,登记书架)。 */
150
+ adaptSave: '/api/dsh-novel-forge/adapt/save',
151
+ /** 改编模式:从源全文 + 编辑后方案提炼新书资料并保存为「待写新书」。 */
152
+ adaptMaterialize: '/api/dsh-novel-forge/adapt/materialize',
153
+ /** 改编模式:rewrite 逐章重写(NDJSON 流式进度)。 */
154
+ adaptRewriteStream: '/api/dsh-novel-forge/adapt/rewrite-stream',
155
+ /** 改编模式:把预览/微调后的新书资料写入并登记书架。 */
156
+ adaptMaterializeSave: '/api/dsh-novel-forge/adapt/materialize-save',
157
+ /** 主题自定义背景:上传图片(POST,存盘并返回服务端 URL)。 */
158
+ themeBackgroundUpload: '/api/dsh-novel-forge/theme/background',
159
+ /** 主题自定义背景:读取已上传文件(GET prefix,/theme/background/<name>)。 */
160
+ themeBackgroundGet: '/api/dsh-novel-forge/theme/background',
86
161
  } as const
87
162
 
88
163
  /** 书架:一本书的条目。 */
@@ -130,6 +205,62 @@ export interface BookRemoveRequest {
130
205
  id: string
131
206
  }
132
207
 
208
+ /** POST /bookshelf/import-dir 请求:导入已有项目目录。 */
209
+ export interface BookImportDirRequest {
210
+ /** 项目目录(须含 novel-project.json)。 */
211
+ outputDir: string
212
+ }
213
+
214
+ /** POST /bookshelf/import-dir 响应。 */
215
+ export interface BookImportDirResponse {
216
+ book: BookEntry
217
+ /** true = 目录已在书架中(本次为重新激活)。 */
218
+ existed: boolean
219
+ }
220
+
221
+ /** POST /bookshelf/import-text 请求:导入 txt/md 全本。两种模式二选一:
222
+ * - filePath:服务器本地文件路径;
223
+ * - text + fileName:浏览器上传的全文内容(fileName 用于推断书名)。
224
+ */
225
+ export interface BookImportTextRequest {
226
+ /** 模式一:源文件绝对路径(txt 或 md)。 */
227
+ filePath?: string
228
+ /** 模式二:浏览器上传的全文内容。 */
229
+ text?: string
230
+ /** 模式二:原文件名(txt/md),用于推断书名与显示。 */
231
+ fileName?: string
232
+ /** 输出目录;缺省为 ~/.dsh/novels/书名。 */
233
+ outputDir?: string
234
+ }
235
+
236
+ /** POST /bookshelf/import-text 响应。 */
237
+ export interface BookImportTextResponse {
238
+ bookName: string
239
+ /** 成功拆出的章节数。 */
240
+ chapters: number
241
+ /** 因内容过短被跳过的章节标题列表。 */
242
+ skipped: string[]
243
+ /** 登记后的书架条目。 */
244
+ book: BookEntry
245
+ }
246
+
247
+ /** POST /bookshelf/import-text/preview 请求:上传全文做拆章预览(不落盘)。 */
248
+ export interface BookImportTextPreviewRequest {
249
+ text: string
250
+ /** 原文件名(txt/md),用于推断书名。 */
251
+ fileName?: string
252
+ }
253
+
254
+ /** POST /bookshelf/import-text/preview 响应。 */
255
+ export interface BookImportTextPreviewResponse {
256
+ /** 预计书名(fileName 去扩展名)。 */
257
+ bookName: string
258
+ /** 识别出的章节(已按正文长度过滤过短章节)。 */
259
+ chapters: Array<{ no: number; title: string; chars: number }>
260
+ /** 因内容过短被跳过的章节标题列表。 */
261
+ skipped: string[]
262
+ }
263
+
133
264
  /** Chapter lifecycle states (the writing pipeline's state machine). */
134
265
  export type ChapterStatus =
135
266
  | 'pending' // planned, not started
@@ -152,6 +283,18 @@ export interface ChapterPlan {
152
283
  beats: string
153
284
  /** Target character count (defaults to the configured chapter size). */
154
285
  targetChars: number
286
+ /** 本章必达项(必须推进的局面/关系/信息/风险/决策变化)。 */
287
+ mustAdvance?: string[]
288
+ /** 本章必须保持/不得破坏的项(如人物状态、已有伏笔不提前揭)。 */
289
+ mustPreserve?: string[]
290
+ /** 本章不可违背的人物硬事实(身份/阵营/境界/当前位置/知情度)。 */
291
+ characterHardFacts?: string[]
292
+ /** 伏笔操作指令(seed/touch/pressure/partial_reveal/payoff/forbid)。 */
293
+ payoffDirectives?: Array<{ no?: number; operation?: 'seed' | 'touch' | 'pressure' | 'partial_reveal' | 'payoff' | 'forbid'; text?: string }>
294
+ /** 章末钩子要求(悬念/反转/新线索/未闭合选择)。 */
295
+ endingHook?: string
296
+ /** 本章义务合约(人类可读摘要,供生成与审稿共同锚定)。 */
297
+ obligation?: string
155
298
  /** Generation/review state. */
156
299
  status: ChapterStatus
157
300
  /** 进入 generating 的时间(用于超时自动复位;未在生成时无此字段)。 */
@@ -168,6 +311,10 @@ export interface ChapterPlan {
168
311
  review?: ReviewReport
169
312
  /** 作者复盘:钩子兑现/结尾钩子/剧情线推进/连续性/节奏趋势(生成后自动)。 */
170
313
  authorReview?: AuthorReview
314
+ /** 本章目标张力 0-100(规划或作者设定;用于张力曲线)。 */
315
+ tension?: number
316
+ /** 本章实际张力 0-100(审稿时模型打分;缺省时回落到 review.tension)。 */
317
+ tensionActual?: number
171
318
  /**
172
319
  * 待确认草稿:润色(去AI味)或整章重写的产物正文。生成时先存这里,
173
320
  * 用户看过对比后点「采纳」才覆盖正文文件;点「放弃」则丢弃。刷新页面不丢失。
@@ -191,18 +338,46 @@ export interface AuthorReview {
191
338
  continuity: string
192
339
  /** 近期节奏趋势提示(拖沓/爽点密度等)。 */
193
340
  trend: string
341
+ /** 本章发生的关键状态变化(人物状态/世界局面/关系/资源),用于回灌整本与事实库。 */
342
+ stateChanges?: string[]
343
+ /** 本章新引入或升级的冲突(供整本控制层与后续卷节奏参考)。 */
344
+ newConflicts?: string[]
345
+ /** 本章埋下/推进的新线索(供知识与伏笔系统回灌)。 */
346
+ clues?: string[]
347
+ /** 本章缺席但值得注意的角色及风险(卷级职责/缺席风险)。 */
348
+ absentRisks?: string[]
194
349
  /** 复盘时间。 */
195
350
  reviewedAt: string
196
351
  }
197
352
 
353
+ /** 审稿维度(结构化定位问题类别;与 review-policy.ts 的 REVIEW_DIMENSIONS 对齐)。 */
354
+ export type ReviewDimension = 'character' | 'setting' | 'redline' | 'writing' | 'pacing' | 'logic' | 'anti-ai' | 'presentation' | 'compliance'
355
+
198
356
  /** One review finding. */
357
+ /** 问题严重度(审稿 / 时间线 / 张力共用)。 */
358
+ export type Severity = 'high' | 'medium' | 'low'
359
+
199
360
  export interface ReviewIssue {
200
361
  /** Severity: high = must fix, medium = should fix, low = suggestion. */
201
- severity: 'high' | 'medium' | 'low'
362
+ severity: Severity
363
+ /** 问题维度(可选;缺省由前端按 item 推断)。 */
364
+ dimension?: ReviewDimension
202
365
  /** What the problem is. */
203
366
  item: string
204
367
  /** Concrete suggestion for fixing it. */
205
368
  suggestion: string
369
+ /** 命中的反 AI 规则名(结构化,便于统计)。 */
370
+ ruleName?: string
371
+ /** 规则类别:forbidden / risk / encourage。 */
372
+ ruleType?: 'forbidden' | 'risk' | 'encourage'
373
+ /** 问题细分类(如 套话 句式 段落 心理 设定)。 */
374
+ category?: string
375
+ /** 命中的原文摘录。 */
376
+ excerpt?: string
377
+ /** 判定理由。 */
378
+ reason?: string
379
+ /** 是否可自动改写。 */
380
+ canAutoRewrite?: boolean
206
381
  }
207
382
 
208
383
  /** AI review report for one chapter. */
@@ -215,6 +390,14 @@ export interface ReviewReport {
215
390
  verdict: string
216
391
  /** Individual findings. */
217
392
  issues: ReviewIssue[]
393
+ /** 风险分 0-100(越高越需人工处理;源自 LLM 复核与本地扫描)。 */
394
+ riskScore?: number
395
+ /** 本地 AI 味指数 0-100(越高越像 AI;LLM 复核锚点,供 UI 展示)。 */
396
+ aiFlavor?: number
397
+ /** 本地扫描命中的高频套话(按次数降序,取前若干)。 */
398
+ aiPhrases?: Array<{ word: string; count: number }>
399
+ /** 本章张力 0-100(审稿模型评分;用于张力曲线的"实际"值)。 */
400
+ tension?: number
218
401
  /** When the review ran. */
219
402
  reviewedAt: string
220
403
  }
@@ -231,6 +414,139 @@ export interface Volume {
231
414
  chapterStart: number
232
415
  /** Last chapter number (inclusive). */
233
416
  chapterEnd: number
417
+ /** 卷级战略(这一卷的定位/承转,如「立威卷」「冲突升级卷」)。 */
418
+ strategy?: string
419
+ /** 卷节奏板(这一卷的节奏安排:起-承-转-合/爽点密度/关键节点)。 */
420
+ pacing?: string
421
+ }
422
+
423
+ /** 开书定盘:面向读者的承诺与流派定位(生成/规划均可引用)。 */
424
+ export interface BookContract {
425
+ /** 一句话卖点/题材承诺。 */
426
+ promise?: string
427
+ /** 主推进模式名(从推进模式库选)。 */
428
+ primaryModeName?: string
429
+ /** 辅助推进模式名。 */
430
+ secondaryModeNames?: string[]
431
+ /** 整体文风基调(一句话)。 */
432
+ tone?: string
433
+ /** 目标平台(如「番茄」)。 */
434
+ targetPlatform?: string
435
+ }
436
+
437
+ /** 书内知识库文档(供生成/规划时检索注入的参考资料)。 */
438
+ export interface KnowledgeDoc {
439
+ id: string
440
+ title: string
441
+ content: string
442
+ updatedAt: string
443
+ }
444
+
445
+ /** POST /knowledge request:增删改知识库文档。 */
446
+ export interface KnowledgeRequest {
447
+ action: 'add' | 'remove' | 'replace'
448
+ doc?: { id?: string; title: string; content: string }
449
+ id?: string
450
+ }
451
+
452
+ /** POST /book-analysis request。 */
453
+ export interface BookAnalysisRequest {
454
+ text: string
455
+ }
456
+
457
+ /** 书分析/拆书结果。 */
458
+ export interface BookAnalysisResult {
459
+ sellingPoints: string[]
460
+ structure: string[]
461
+ lessons: string[]
462
+ risks: string[]
463
+ }
464
+
465
+ /** POST /idea-inspiration request。 */
466
+ export interface IdeaInspirationRequest {
467
+ idea: string
468
+ count?: number
469
+ }
470
+
471
+ /** 创意灵感结果:多方向开书灵感。 */
472
+ export interface IdeaInspirationResult {
473
+ ideas: Array<{ title: string; hook: string; genre: string; pov: string; payoff: string }>
474
+ }
475
+
476
+ /** POST /director request。 */
477
+ export interface DirectorRequest {
478
+ focus?: string
479
+ }
480
+
481
+ /** 自动导演编排建议(下一卷/阶段编排 + 修复再平衡)。 */
482
+ export interface DirectorAdvice {
483
+ summary: string
484
+ nextArc: string[]
485
+ pacing: string
486
+ risks: string[]
487
+ fixes: string[]
488
+ }
489
+
490
+ /** 自动导演「采纳」后生成的书内待办项。 */
491
+ export interface DirectorTodo {
492
+ id: string
493
+ text: string
494
+ /** 来源:风险 或 修复。 */
495
+ source: 'risk' | 'fix'
496
+ done: boolean
497
+ createdAt: string
498
+ }
499
+
500
+ /** 题材雷达:单条市场信号。 */
501
+ export interface MarketRadarSignal {
502
+ id: string
503
+ kind: 'genre' | 'protagonist' | 'advantage' | 'opening' | 'relationship' | 'title_pattern' | 'opportunity' | 'crowding'
504
+ title: string
505
+ detail: string
506
+ /** 趋势:current / rising / stable / falling。 */
507
+ direction?: 'current' | 'rising' | 'stable' | 'falling'
508
+ /** 是否建议优先考虑。 */
509
+ recommended?: boolean
510
+ }
511
+
512
+ /** 题材雷达:生产底座(引用内置题材/推进模式库,或给出新资产)。 */
513
+ export interface ProductionFoundation {
514
+ genre: { existingId?: string; name: string; description: string; template?: string }
515
+ primaryStoryMode: { existingId?: string; name: string; driver: string; readerExpectation: string }
516
+ secondaryStoryMode?: { existingId?: string; name: string; driver: string; readerExpectation: string }
517
+ }
518
+
519
+ /** 题材雷达:开书创意简报(可执行,严禁照搬具体作品/命名)。 */
520
+ export interface MarketCreativeBrief {
521
+ promptBlock: string
522
+ openingIdea: string
523
+ coreAdvantage: string
524
+ bookSellingPoint: string
525
+ first30ChapterPromise: string
526
+ }
527
+
528
+ /** 题材雷达结果。 */
529
+ export interface MarketRadarResult {
530
+ signals: MarketRadarSignal[]
531
+ productionFoundation: ProductionFoundation
532
+ /** 开书创意简报(可选;用「用信号创作」接口单独生成)。 */
533
+ creativeBrief?: MarketCreativeBrief
534
+ }
535
+
536
+ /** POST /market-radar request。 */
537
+ export interface MarketRadarRequest {
538
+ platform?: string
539
+ genre?: string
540
+ keywords?: string
541
+ feedText?: string
542
+ /** 已扫描的上榜记录(来自真实榜单抓取),用于让分析基于真实榜单证据。 */
543
+ candidates?: Array<{ title: string; author?: string; tags?: string[]; synopsis?: string; category?: string; heatLabel?: string }>
544
+ }
545
+
546
+ /** POST /market-radar/brief request:用选中的信号 + 影响模式生成开书创意。 */
547
+ export interface MarketRadarBriefRequest {
548
+ influenceMode: 'follow_hot' | 'differentiate' | 'light'
549
+ signals: MarketRadarSignal[]
234
550
  }
235
551
 
236
552
  /** A character card from the story bible. */
@@ -264,6 +580,175 @@ export interface StoryBible {
264
580
  }
265
581
 
266
582
  /** A planted/active/resolved foreshadowing thread. */
583
+ /** 修订建议来源:审稿 / 时间线 / 张力。 */
584
+ export type RevisionSource = 'review' | 'timeline' | 'tension'
585
+
586
+ /** 一条待修订条目(合并层排序后的最小单位)。 */
587
+ export interface RevisionItem {
588
+ /** 稳定 id(source:chapter:index)。 */
589
+ id: string
590
+ source: RevisionSource
591
+ severity: Severity
592
+ /** 归属章节号(0 = 全书级)。 */
593
+ chapterNo: number
594
+ item: string
595
+ suggestion: string
596
+ /** 去重时合并掉的同类条数(>=2 时展示)。 */
597
+ count?: number
598
+ }
599
+
600
+ /** POST /revision/plan 请求:把该章三类建议合并成一份修订指令。 */
601
+ export interface RevisionPlanRequest {
602
+ op: 'plan'
603
+ chapterNo?: number
604
+ /** 显式指定的审稿意见(面板勾选后传入;缺省取已落盘报告)。 */
605
+ reviewIssues?: ReviewIssue[]
606
+ includeTimeline?: boolean
607
+ includeTension?: boolean
608
+ bookId?: string
609
+ }
610
+
611
+ /** POST /revision/plan 响应。 */
612
+ export interface RevisionPlanResponse {
613
+ chapterNo: number
614
+ items: RevisionItem[]
615
+ /** 唯一修订指令(面板直接把它交给 /rewrite)。 */
616
+ instruction: string
617
+ counts: Record<RevisionSource, number>
618
+ /** 因上限被截断的条数。 */
619
+ omitted: number
620
+ /** 验证基准(复核时逐条核对本轮下发的全部条目)。 */
621
+ baseline: ReviewReport
622
+ /** 一行摘要。 */
623
+ summary: string
624
+ }
625
+
626
+ /**
627
+ * 张力曲线形状预设:
628
+ * `escalation` 递进爬升 / `suspense` 悬疑加压 / `wave` 波浪呼吸 /
629
+ * `frontLoad` 前紧后稳 / `flat` 平稳推进 / `custom` 自定义。
630
+ */
631
+ export type TensionCurvePreset = 'escalation' | 'suspense' | 'wave' | 'frontLoad' | 'flat' | 'custom'
632
+
633
+ /** 张力曲线配置(随项目保存)。 */
634
+ export interface TensionCurveConfig {
635
+ preset: TensionCurvePreset
636
+ /** preset=custom 时的逐章采样(0-100;缺省按章节数取默认值)。 */
637
+ custom?: number[]
638
+ }
639
+
640
+ /** 张力曲线的一条问题(实际 vs 目标 / 曲线形状)。 */
641
+ export interface TensionIssue {
642
+ severity: 'high' | 'medium' | 'low'
643
+ chapters: number[]
644
+ item: string
645
+ suggestion: string
646
+ }
647
+
648
+ /** 张力曲线数据点(面板绘图用)。 */
649
+ export interface TensionCurvePoint {
650
+ no: number
651
+ title: string
652
+ /** 目标张力。 */
653
+ target?: number
654
+ /** 实际张力(审稿打分)。 */
655
+ actual?: number
656
+ /** 参考曲线在此处的取值。 */
657
+ reference?: number
658
+ }
659
+
660
+ /** GET /tension 响应。 */
661
+ export interface TensionResponse {
662
+ preset: TensionCurvePreset
663
+ points: TensionCurvePoint[]
664
+ /** 规则核对发现的问题。 */
665
+ issues: TensionIssue[]
666
+ }
667
+
668
+ /** POST /tension 请求。 */
669
+ export interface TensionRequest {
670
+ op: 'preset' | 'set' | 'clear'
671
+ preset?: TensionCurvePreset
672
+ chapterNo?: number
673
+ /** op=set 时的目标张力(0-100)。 */
674
+ tension?: number
675
+ }
676
+
677
+ /** 允许作者编辑的提示词槽位 id(白名单)。 */
678
+ export type PromptSlotId = 'styleExtra' | 'antiAiExtra' | 'dialogueExtra' | 'endingHookExtra'
679
+
680
+ /** 一个提示词槽位的当前内容。 */
681
+ export interface PromptSlotState {
682
+ id: PromptSlotId
683
+ label: string
684
+ hint: string
685
+ placeholder: string
686
+ maxChars: number
687
+ value: string
688
+ }
689
+
690
+ /** GET /prompt-slots 响应。 */
691
+ export interface PromptSlotsResponse {
692
+ slots: PromptSlotState[]
693
+ }
694
+
695
+ /** POST /prompt-slots 请求:设置或清空一个槽位。 */
696
+ export interface PromptSlotsRequest {
697
+ id: PromptSlotId
698
+ /** 空串 = 清空该槽位(恢复默认)。 */
699
+ value: string
700
+ }
701
+
702
+ /**
703
+ * 故事时间线事件:从章节正文抽取的「故事内时间点 + 地点 + 参与角色 + 事件」。
704
+ * 用途:后续章节的时间连续性与地点衔接(比编年录更强调"顺序")。
705
+ */
706
+ export interface TimelineEvent {
707
+ /** 稳定 id(时间线内唯一)。 */
708
+ id: string
709
+ /** 所属章节号。 */
710
+ chapterNo: number
711
+ /** 故事内时间点(如「第三日黄昏」「入宗三个月后」「同日夜」)。 */
712
+ time: string
713
+ /** 相对顺序(同书内递增;无法判断时缺省)。用于检测时间倒流。 */
714
+ order?: number
715
+ /** 地点。 */
716
+ place: string
717
+ /** 参与角色(角色名)。 */
718
+ characters: string[]
719
+ /** 事件一句话。 */
720
+ event: string
721
+ /** 来源:模型抽取 / 作者手改。 */
722
+ source: 'extracted' | 'manual'
723
+ createdAt: string
724
+ }
725
+
726
+ /** 时间线矛盾(规则初筛 + AI 复核)。 */
727
+ export interface TimelineIssue {
728
+ severity: 'high' | 'medium' | 'low'
729
+ /** 定位到的章节(可多个)。 */
730
+ chapters: number[]
731
+ /** 问题描述。 */
732
+ item: string
733
+ /** 建议修法。 */
734
+ suggestion: string
735
+ }
736
+
737
+ /** GET /timeline 响应。 */
738
+ export interface TimelineResponse {
739
+ events: TimelineEvent[]
740
+ /** 规则初筛发现的问题(瞬时计算,不落盘)。 */
741
+ issues?: TimelineIssue[]
742
+ }
743
+
744
+ /** POST /timeline 请求:op=extract 抽单章 / check 全量检查 / update 手改 / remove 删除 / clear 清空。 */
745
+ export interface TimelineRequest {
746
+ op: 'extract' | 'check' | 'update' | 'remove' | 'clear'
747
+ chapterNo?: number
748
+ event?: TimelineEvent
749
+ id?: string
750
+ }
751
+
267
752
  export interface Foreshadow {
268
753
  /** Stable id. */
269
754
  id: string
@@ -305,6 +790,8 @@ export interface AuditResponse {
305
790
  auditedChapters: number
306
791
  /** 质检时间。 */
307
792
  auditedAt: string
793
+ /** 本次质检使用的模型(auditModel 或全局 model)。 */
794
+ model?: string
308
795
  }
309
796
 
310
797
  /** 全书质检的实时状态(通过 /status 暴露给面板/外部读取)。 */
@@ -376,7 +863,7 @@ export interface PlotlineHealthReport {
376
863
  }>
377
864
  }
378
865
 
379
- /** AI 剧情方案:下一阶段目标 + 建议新线。 */
866
+ /** 剧情方案:下一阶段目标 + 建议新线。 */
380
867
  export interface PlotlinePlan {
381
868
  /** 下一阶段(未来 5-10 章)剧情方向。 */
382
869
  direction: string
@@ -387,7 +874,7 @@ export interface PlotlinePlan {
387
874
  /** POST /plotlines 响应。 */
388
875
  export interface PlotlinesResponse {
389
876
  plotlines: Plotline[]
390
- /** op=suggest 时的 AI 建议候选线。 */
877
+ /** op=suggest 时的 建议候选线。 */
391
878
  suggestions?: Plotline[]
392
879
  /** op=health 时的健康检查报告。 */
393
880
  health?: PlotlineHealthReport
@@ -508,7 +995,7 @@ export interface RoleStatusCard {
508
995
  appearances: number
509
996
  }
510
997
 
511
- /** 角色库条目(主表:作者维护 + AI 提炼 + 编年录自动聚合)。 */
998
+ /** 角色库条目(主表:作者维护 + 提炼 + 编年录自动聚合)。 */
512
999
  export interface RoleRecord {
513
1000
  /** 角色名(唯一键)。 */
514
1001
  name: string
@@ -528,122 +1015,33 @@ export interface RoleRecord {
528
1015
  knowledge: string[]
529
1016
  /** 首次出场章节(编年录聚合,可手动修正)。 */
530
1017
  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
1018
  }
562
1019
 
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 时的场景名。 */
1020
+ /** POST /roles 请求:角色库增删改 + 提炼 + 参考图上传。 */
1021
+ export interface RolesRequest {
1022
+ op: 'extract' | 'adopt' | 'update' | 'remove'
1023
+ /** adopt / update 时传入的角色(adopt 可修改后采纳)。 */
1024
+ role?: RoleRecord
1025
+ /** remove 时的角色名。 */
609
1026
  name?: string
610
- /** op='image' 时的图片 dataURL 与用途标签(全景/局部/氛围)。 */
611
- dataUrl?: string
612
- label?: string
613
1027
  }
614
1028
 
615
- /** POST /visual-rules 请求:视觉世界观规则提炼 / 保存。 */
616
- export interface VisualRulesRequest {
617
- op: 'extract' | 'save'
618
- /** op=save 时的规则数组。 */
619
- rules?: string[]
620
- }
621
1029
 
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[]
1030
+ /** POST /llm-test 请求:对选中的提供商/模型发一次最小真实调用。 */
1031
+ export interface LlmTestRequest {
1032
+ provider: string
1033
+ model: string
632
1034
  }
633
1035
 
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
1036
+ /** POST /llm-test 响应。 */
1037
+ export interface LlmTestResponse {
1038
+ ok: boolean
1039
+ /** 连通延迟(毫秒)。 */
1040
+ ms?: number
1041
+ /** 失败原因(已映射为人话)。 */
1042
+ message?: string
1043
+ /** 稳定错误码(LlmError code),便于排查。 */
1044
+ code?: string
647
1045
  }
648
1046
 
649
1047
  /** POST /roles 响应。 */
@@ -651,15 +1049,9 @@ export interface RolesResponse {
651
1049
  roles: RoleRecord[]
652
1050
  /** op=extract 时的 AI 候选角色。 */
653
1051
  candidates?: RoleRecord[]
654
- /** op=visual 时的动漫形象描述词(已写入角色卡)。 */
655
- visual?: RoleRecord['imagePrompt']
656
- /** op=promptKit 时的四类提示词精修包(已写入角色卡)。 */
657
- promptKit?: RoleRecord['promptKit']
658
- /** op=image 时的角色参考图 dataURL。 */
659
- imageUrl?: string
660
1052
  }
661
1053
 
662
- /** POST /bible/patch 请求:局部修补设定圣经。 */
1054
+ /** POST /bible/patch 请求:局部修补道藏。 */
663
1055
  export interface BiblePatchRequest {
664
1056
  worldRules?: string[]
665
1057
  redLines?: string[]
@@ -668,10 +1060,10 @@ export interface BiblePatchRequest {
668
1060
  characters?: CharacterCard[]
669
1061
  }
670
1062
 
671
- /** POST /blurb 请求:AI 生成/补全或手动保存小说简介。 */
1063
+ /** POST /blurb 请求:生成/补全或手动保存小说简介。 */
672
1064
  export interface BlurbRequest {
673
1065
  action: 'generate' | 'save'
674
- /** 已写好的开头(AI 补全时使用;留空 = 全量生成)。 */
1066
+ /** 已写好的开头(补全时使用;留空 = 全量生成)。 */
675
1067
  partial?: string
676
1068
  /** 手动保存的完整简介(action=save 时)。 */
677
1069
  text?: string
@@ -743,7 +1135,7 @@ export interface WorldState {
743
1135
  factions: WorldFaction[]
744
1136
  }
745
1137
 
746
- /** POST /world 请求:AI 提炼或手动保存。 */
1138
+ /** POST /world 请求:提炼或手动保存。 */
747
1139
  export interface WorldRequest {
748
1140
  action: 'generate' | 'save'
749
1141
  /** action=save 时的完整世界数据。 */
@@ -775,31 +1167,172 @@ export interface ProjectState {
775
1167
  assets?: ProjectAssets
776
1168
  /** 事实库/时间线:每章生成后抽取,注入后续章节保持一致性。 */
777
1169
  facts?: ChapterFact[]
778
- /** 小说简介(面向读者的作品门面,AI 生成或手动保存)。 */
1170
+ /** 书内知识库文档(可检索资料/设定/参考)。 */
1171
+ knowledgeDocs?: KnowledgeDoc[]
1172
+ /** 自动导演待办:风险/修复「采纳」后生成的随手清单。 */
1173
+ todos?: DirectorTodo[]
1174
+ /** 小说简介(面向读者的作品门面,生成或手动保存)。 */
779
1175
  blurb?: string
1176
+ /** 开书定盘:书籍级承诺与流派定位(前30章承诺/主副模式/文风/平台)。 */
1177
+ bookContract?: BookContract
780
1178
  /** 封面文件名(相对输出目录,如 cover.png)。 */
781
1179
  coverPath?: string
782
1180
  /** 大世界结构化数据(境界体系/区域/势力)。 */
783
1181
  world?: WorldState
784
1182
  /** 剧情线(主线/支线/人物线/悬念线)。 */
785
1183
  plotlines?: Plotline[]
786
- /** 角色库(作者维护 + AI 提炼的主表)。 */
1184
+ /** 角色库(作者维护 + 提炼的主表)。 */
787
1185
  roles?: RoleRecord[]
788
- /** 场景库(作者维护 + AI 提炼的主表)。 */
789
- scenes?: SceneCard[]
790
- /** 视觉世界观规则(生图/生视频必须遵守,从道藏提炼,注入所有提示词)。 */
791
- visualRules?: string[]
792
1186
  /** 人物志:角色当前状态聚合结果(从编年录刷新后存档,打开页面直接显示)。 */
793
1187
  roleStatus?: RoleStatusCard[]
794
- /** 漫剧分镜结果缓存:章号 → 分镜(持久化,刷新不丢)。 */
795
- /** 漫剧分集计划缓存:卷号/0=全书 → 分集计划(持久化,刷新不丢)。 */
796
- /** 漫画脚本缓存:章号 → 漫画脚本(持久化,刷新不丢)。 */
1188
+ /** 故事时间线(逐章抽取:时间点 / 地点 / 参与角色 / 事件)。 */
1189
+ timeline?: TimelineEvent[]
1190
+ /** 张力曲线配置(形状预设 + 自定义采样)。 */
1191
+ tensionCurve?: TensionCurveConfig
1192
+ /** 作者自定义的提示词槽位(白名单见 prompt-slots.ts)。 */
1193
+ promptSlots?: Partial<Record<PromptSlotId, string>>
1194
+ /** 本书参数(写作/审稿/推理/模型快切;未设字段回退全局 config)。 */
1195
+ bookSettings?: BookSettings
797
1196
  /** ISO timestamps. */
798
1197
  createdAt: string
799
1198
  updatedAt: string
800
1199
  }
801
1200
 
802
- /** Runtime config surface exposed to the panel (subset of plugin Config). */
1201
+ /** 本书参数(存 novel-project.json.bookSettings;未设字段回退全局 config)。 */
1202
+ export interface BookSettings {
1203
+ /** 本书使用的提供方路由(快切器写入)。 */
1204
+ provider?: string
1205
+ /** 本书使用的主模型 id。 */
1206
+ model?: string
1207
+ /** 本书写作推理档位。 */
1208
+ reasoningEffort?: 'off' | 'low' | 'high' | 'max'
1209
+ /** 本书分析类任务推理档位。 */
1210
+ analysisReasoning?: 'off' | 'low' | 'high' | 'max'
1211
+ /** 本书每章目标字数。 */
1212
+ chapterChars?: number
1213
+ /** 本书单章最大输出 tokens。 */
1214
+ maxTokens?: number
1215
+ /** 本书审稿通过分。 */
1216
+ reviewPassScore?: number
1217
+ /** 本书是否写完自动审稿。 */
1218
+ autoReview?: boolean
1219
+ /** 本书是否自动作者复盘。 */
1220
+ autoAuthorReview?: boolean
1221
+ /** 本书是否修稿后自动复审。 */
1222
+ autoReviewAfterRevise?: boolean
1223
+ }
1224
+
1225
+ /** 手动添加的模型库条目(只存插件内,不改 DSH 全局)。 */
1226
+ export interface SavedModel {
1227
+ /** 唯一 id(前端生成的短 id)。 */
1228
+ id: string
1229
+ /** 展示名(可为空,回退到 model)。 */
1230
+ name: string
1231
+ /** DSH 提供商路由(如 zai-coding-cn)。 */
1232
+ provider: string
1233
+ /** 模型 id(如 glm-5.3-flash)。 */
1234
+ model: string
1235
+ }
1236
+
1237
+ /** DSH 模型添加:厂商预设(选择厂商,直接填 API Key)。 */
1238
+ export interface LlmVendor {
1239
+ id: string
1240
+ name: string
1241
+ /** 该厂商对应的 provider 路由。 */
1242
+ route: string
1243
+ /** DSH 凭据引用名(写入 .credentials.yaml 的 refs)。 */
1244
+ apiKeyEnv: string
1245
+ /** 默认模型 id。 */
1246
+ defaultModel: string
1247
+ /** 建议可选模型 id 列表(下拉 data-list 用)。 */
1248
+ models: string[]
1249
+ /** 内置适配器(如 deepseek-official),无需注册 pi-ai 路由。 */
1250
+ builtin?: boolean
1251
+ }
1252
+
1253
+ /** 预置的常见厂商(id=provider 路由;添加模型下拉兜底用,其余厂商由运行时目录动态补充)。 */
1254
+ export const LLM_VENDORS: LlmVendor[] = [
1255
+ // 注意:本列表只是「运行时目录不可用」时的兜底建议值;实际以 ctx.llm.listModels() 为准
1256
+ // (见 engine.ts listLlmVendors),避免 DSH 侧模型改名后这里的条目过期。
1257
+ { id: 'deepseek-official', name: 'DeepSeek', route: 'deepseek-official', apiKeyEnv: 'DEEPSEEK_API_KEY', defaultModel: 'deepseek-flash', models: ['deepseek-flash', 'deepseek-v4-pro'], builtin: true },
1258
+ { 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'] },
1259
+ { 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'] },
1260
+ { 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'] },
1261
+ ]
1262
+
1263
+ /** 运行时厂商目录的一项(添加到模型下拉;由 DSH 的 pi-ai 可配置提供方动态生成)。 */
1264
+ export interface LlmVendorOption {
1265
+ /** provider 路由 id(也是厂商下拉的值)。 */
1266
+ id: string
1267
+ /** 展示名。 */
1268
+ name: string
1269
+ /** 建议模型 id(可为空,用户手填)。 */
1270
+ models: string[]
1271
+ /** 已知 DSH 凭据引用名;为空时 host 生成 `PI_AI_<ID>_API_KEY`。 */
1272
+ apiKeyEnv?: string
1273
+ /** 内置适配器(只写凭据,不注册 pi-ai 路由)。 */
1274
+ builtin?: boolean
1275
+ }
1276
+
1277
+ /** GET /llm-vendors 响应。 */
1278
+ export interface LlmVendorsResponse {
1279
+ vendors: LlmVendorOption[]
1280
+ }
1281
+
1282
+ /** /llm-models 里的一条模型。 */
1283
+ export interface LlmModelOption { id: string; name: string }
1284
+
1285
+ /** GET /llm-models?provider=x 响应。 */
1286
+ export interface LlmModelsResponse {
1287
+ models: LlmModelOption[]
1288
+ }
1289
+
1290
+ /** GET /llm-providers 响应:当前已注册的提供方路由。 */
1291
+ export interface LlmProvidersResponse {
1292
+ providers: { id: string; name: string }[]
1293
+ }
1294
+
1295
+ /** POST /llm-remove 请求:移除一个提供方(unset key + 移除 llm-pi-ai 路由)。 */
1296
+ export interface RemoveProviderRequest {
1297
+ provider: string
1298
+ /** 该提供方对应的 DSH 凭据引用名(用于 unset)。 */
1299
+ apiKeyEnv?: string
1300
+ }
1301
+
1302
+ /** POST /llm-remove 响应。 */
1303
+ export interface RemoveProviderResponse {
1304
+ ok: boolean
1305
+ message?: string
1306
+ }
1307
+
1308
+ /** POST /llm-add 请求:添加一个模型(厂商直填 key,或自定义路由)。 */
1309
+ export interface AddModelRequest {
1310
+ mode: 'vendor' | 'custom'
1311
+ /** 厂商模式用:provider 路由 id(来自 /llm-vendors)。 */
1312
+ vendor?: string
1313
+ /** 厂商已知的 DSH 凭据引用名(可选;为空时 host 生成)。 */
1314
+ apiKeyEnv?: string
1315
+ /** 自定义模式用:provider 路由 id。 */
1316
+ provider?: string
1317
+ /** 模型 id。 */
1318
+ model: string
1319
+ /** API Key。 */
1320
+ apiKey: string
1321
+ /** 展示名(可选)。 */
1322
+ name?: string
1323
+ /** 自定义模式用:OpenAI 兼容 base URL。 */
1324
+ baseURL?: string
1325
+ }
1326
+
1327
+ /** POST /llm-add 响应。 */
1328
+ export interface AddModelResponse {
1329
+ ok: boolean
1330
+ saved: SavedModel
1331
+ provider: string
1332
+ message?: string
1333
+ }
1334
+
1335
+ /** 手动添加的模型库条目(只存插件内,不改 DSH 全局)。 */
803
1336
  export interface NovelConfig {
804
1337
  /** Absolute path of the default docx outline to load. */
805
1338
  outlinePath: string
@@ -807,10 +1340,25 @@ export interface NovelConfig {
807
1340
  outputDir: string
808
1341
  /** LLM provider route (e.g. deepseek-official). */
809
1342
  provider: string
810
- /** LLM model id (e.g. deepseek-v4-flash). */
1343
+ /** LLM model id (e.g. deepseek-flash). */
811
1344
  model: string
1345
+ /** 生成正文用模型(缺省用 model)。 */
1346
+ generateModel?: string
1347
+ /** 审稿用模型(缺省用 model;建议用更强的 reasoner/pro)。 */
1348
+ reviewModel?: string
1349
+ /** 全书质检(审计)用模型(缺省用 model)。 */
1350
+ auditModel?: string
1351
+ /**
1352
+ * 备用模型:主模型调用失败(网络/限流/额度/服务不可用)时自动切换重试一次。
1353
+ * 留空表示不切换。批量连写时能显著减少"整批中断"。
1354
+ */
1355
+ fallbackModel?: string
1356
+ /** 是否在出章后自动抽取故事时间线(失败不阻断出章)。默认开。 */
1357
+ autoTimeline?: boolean
812
1358
  /** LLM reasoning effort: off = no thinking; low/high/max = thinking intensity. */
813
1359
  reasoningEffort: 'off' | 'low' | 'high' | 'max'
1360
+ /** 分析类任务(提炼/拆书/反推大纲等)的推理档位;默认 low,不受上面写作档位影响。 */
1361
+ analysisReasoning: 'off' | 'low' | 'high' | 'max'
814
1362
  /** Target characters per chapter. */
815
1363
  chapterChars: number
816
1364
  /** Max output tokens per chapter call. */
@@ -823,15 +1371,192 @@ export interface NovelConfig {
823
1371
  autoAuthorReview: boolean
824
1372
  /** 修订/润色产出草稿后是否自动附带一次 AI 审查(工作区显示新稿评分与剩余问题)。 */
825
1373
  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
1374
+ /** 自定义背景图(URL 或 dataURL 或服务端路径引用;空 = 使用主题默认背景)。 */
1375
+ themeBackground?: string
1376
+ /** 自定义背景遮罩/模糊强度 0-80(0 = 不遮罩)。 */
1377
+ themeBackgroundBlur?: number
1378
+ /** 玻璃透明度 0-100(100=当前原样,越小越透,新拟态/黏土可见背景图)。 */
1379
+ themeOpacity?: number
1380
+ /** 是否启用改编模式(默认关闭;发布后开启)。 */
1381
+ enableAdaptMode?: boolean
1382
+ /** 手动添加的模型库(「我的模型」条目;只存插件内)。 */
1383
+ savedModels?: SavedModel[]
1384
+ }
1385
+
1386
+ /** POST /move-output-dir request:dryRun=true 仅预览;确认时须带 to。 */
1387
+ export interface MoveOutputDirRequest {
1388
+ /** 新输出目录(绝对路径)。 */
1389
+ to?: string
1390
+ /** 只列出当前目录内容,不搬移。 */
1391
+ dryRun?: boolean
1392
+ }
1393
+
1394
+ /** POST /move-output-dir response。 */
1395
+ export interface MoveOutputDirResponse {
1396
+ from: string
1397
+ to?: string
1398
+ /** 当前(或迁移后)目录内容清单。 */
1399
+ files: string[]
1400
+ bytes: number
1401
+ /** 联动重指向的书架条目数。 */
1402
+ movedBooks: number
1403
+ /** settings 默认输出目录是否同步更新。 */
1404
+ defaultUpdated: boolean
1405
+ }
1406
+
1407
+ /** POST /book-settings request:patch 省略 = 读取;字段传 null = 删除本书覆盖(回退全局)。 */
1408
+ export interface BookSettingsRequest {
1409
+ patch?: { [K in keyof BookSettings]?: BookSettings[K] | null }
1410
+ }
1411
+
1412
+ /** POST /book-settings response。 */
1413
+ export interface BookSettingsResponse {
1414
+ /** 本书已设置的参数(未设字段缺省 = 回退全局)。 */
1415
+ settings: BookSettings
1416
+ /** 应用回退链后的生效配置(全局 + 本书覆盖)。 */
1417
+ effective: NovelConfig
1418
+ /** 当前是否有打开的书。 */
1419
+ hasBook: boolean
832
1420
  }
833
1421
 
834
1422
  /** GET /status response. */
1423
+ /**
1424
+ * 创作阶段契约(宿主计算的「当前阶段 → 本轮允许的动作」)。
1425
+ * 计算逻辑在 stage-contract.ts;这里是宿主与面板/助手共享的线上形状。
1426
+ */
1427
+ export interface StageInfo {
1428
+ /** 阶段标识。 */
1429
+ id: 'outline' | 'bible' | 'plan' | 'write' | 'wait' | 'review' | 'revise' | 'export'
1430
+ /** 中文阶段名。 */
1431
+ label: string
1432
+ /** 建议的下一步动作(助手工具名;无对应工具时为空数组)。 */
1433
+ recommend: string[]
1434
+ /** 本阶段允许的写操作(作者只说了「继续」时的唯一命令集)。 */
1435
+ allow: string[]
1436
+ /** 为什么处于该阶段。 */
1437
+ reason: string
1438
+ }
1439
+
1440
+ // ------------------------------------------------------------ LLM 实况 / 用量
1441
+
1442
+ /** 单次 LLM 调用的 token 用量(来自 dsh-llm 的 usage chunk)。 */
1443
+ export interface LlmTokenUsage {
1444
+ inputTokens: number
1445
+ outputTokens: number
1446
+ /** 供应商给出的总用量(缺失时由输入+输出推导)。 */
1447
+ totalTokens?: number
1448
+ /** 思考(reasoning)通道用量。 */
1449
+ reasoningTokens?: number
1450
+ /** 命中缓存的输入用量。 */
1451
+ cacheReadTokens?: number
1452
+ }
1453
+
1454
+ /** LLM 实况帧:宿主 → 浏览器的 SSE 事件(每次调用一组 session_* 事件)。 */
1455
+ export interface LlmLiveFrame {
1456
+ type: 'session_started' | 'output_delta' | 'reasoning_delta' | 'phase_changed' | 'session_completed'
1457
+ /** 宿主生成,形如 ll-<base36>-<n>。 */
1458
+ sessionId: string
1459
+ /** 本次调用用途(如 正文生成/审稿/章节规划)。 */
1460
+ label?: string
1461
+ /** 使用模型。 */
1462
+ model?: string
1463
+ /** 事件时间(ISO)。 */
1464
+ at: string
1465
+ /** session_started:交互上下文。 */
1466
+ context?: { taskId?: string; interactionId: string }
1467
+ /** output_delta / reasoning_delta:本次增量文本。 */
1468
+ content?: string
1469
+ /** session 累计字符数。 */
1470
+ totalChars?: number
1471
+ /** reasoning 累计字符数。 */
1472
+ totalReasoningChars?: number
1473
+ /** phase_changed:新阶段。 */
1474
+ phase?: 'requesting' | 'streaming' | 'completed' | 'failed'
1475
+ /** phase_changed:阶段描述。 */
1476
+ phaseMessage?: string
1477
+ /** session_completed:最终预览(截断)。 */
1478
+ preview?: string
1479
+ /** session_completed:失败信息。 */
1480
+ error?: string
1481
+ /** session_completed:本次用量(供应商未上报时缺省)。 */
1482
+ usage?: LlmTokenUsage
1483
+ /** session_completed:本次调用耗时(毫秒)。 */
1484
+ elapsedMs?: number
1485
+ /** session_completed:首字耗时(毫秒;未拿到文本时缺省)。 */
1486
+ firstTokenMs?: number
1487
+ /** session_started:是否已记录可查看的 Prompt(面板据此显示「查看 Prompt」)。 */
1488
+ hasPrompt?: boolean
1489
+ /** session_started:Prompt 字符数(system + user)。 */
1490
+ promptChars?: number
1491
+ }
1492
+
1493
+ /** 按用途分组的用量。 */
1494
+ export interface LlmUsageBucket {
1495
+ label: string
1496
+ calls: number
1497
+ failed: number
1498
+ inputTokens: number
1499
+ outputTokens: number
1500
+ reasoningTokens: number
1501
+ elapsedMs: number
1502
+ }
1503
+
1504
+ /** 本次运行(进程内,重启归零)的 LLM 用量汇总。 */
1505
+ export interface LlmUsageSummary {
1506
+ calls: number
1507
+ failed: number
1508
+ inputTokens: number
1509
+ outputTokens: number
1510
+ reasoningTokens: number
1511
+ totalTokens: number
1512
+ elapsedMs: number
1513
+ /** 供应商未上报 usage 的调用次数(用于说明数据为何不完整)。 */
1514
+ callsWithoutUsage: number
1515
+ byLabel: LlmUsageBucket[]
1516
+ }
1517
+
1518
+ /** 一次调用的 Prompt 记录(供面板查看「实际发送了什么」)。 */
1519
+ export interface LlmPromptRecord {
1520
+ sessionId: string
1521
+ label?: string
1522
+ model?: string
1523
+ at: string
1524
+ system?: string
1525
+ user?: string
1526
+ /** system + user 的字符数(记录被截断时仍给出原始长度)。 */
1527
+ chars: number
1528
+ /** 记录本身是否被截断。 */
1529
+ truncated?: boolean
1530
+ }
1531
+
1532
+ /** 章节历史版本(快照):覆盖写入前自动留存,可回滚。 */
1533
+ export interface ChapterSnapshot {
1534
+ id: string
1535
+ chapterNo: number
1536
+ /** 快照文件(相对书目录)。 */
1537
+ file: string
1538
+ /** 留存原因(生成覆盖 / 采纳草稿 / 修订 / 手工)。 */
1539
+ reason: string
1540
+ chars: number
1541
+ at: string
1542
+ }
1543
+
1544
+ /** GET /snapshot 响应。 */
1545
+ export interface SnapshotResponse {
1546
+ snapshots: ChapterSnapshot[]
1547
+ /** 快照占用字节数。 */
1548
+ bytes: number
1549
+ }
1550
+
1551
+ /** POST /snapshot 请求:op=create 手工存档 / restore 回滚 / remove 删除 / prune 只留最近 N 个。 */
1552
+ export interface SnapshotRequest {
1553
+ op: 'create' | 'restore' | 'remove' | 'prune'
1554
+ chapterNo?: number
1555
+ id?: string
1556
+ /** prune:每章保留数量。 */
1557
+ keep?: number
1558
+ }
1559
+
835
1560
  export interface StatusResponse {
836
1561
  config: NovelConfig
837
1562
  /** The persisted project, when one exists in the output dir. */
@@ -840,11 +1565,26 @@ export interface StatusResponse {
840
1565
  generatedFiles: string[]
841
1566
  /** 全书质检实时状态(用于面板/外部读取进度)。 */
842
1567
  audit?: AuditStatus
1568
+ /** 宿主按项目真实状态算出的创作阶段(面板角标 / 外部自动化共用)。 */
1569
+ stage?: StageInfo
1570
+ /** 本次运行(进程内)的 LLM 用量汇总:调用次数 / 输入·输出·思考 token / 耗时。 */
1571
+ usage?: LlmUsageSummary
1572
+ /**
1573
+ * 截断声明:本次响应中被裁掉的字段说明(如「编年录:共 320 条,仅返回最近 80 条」)。
1574
+ * 消费方不得把缺失字段当作"不存在",需要完整数据时走专用接口。
1575
+ */
1576
+ truncations?: string[]
843
1577
  }
844
1578
 
845
1579
  /** 生产单状态(生产单 = 区间批量生产执行器:计划补足 + 逐章生成 + 被拒分级处理)。 */
846
1580
  export interface RunState {
847
1581
  runId: string
1582
+ /**
1583
+ * 本批次归属的书名(可选,兼容旧 run-state.json)。
1584
+ * 生产单是全局单实例,而 /run/status 恢复时会扫书架取第一个有 run-state 的目录,
1585
+ * 因此"这是哪本书的批次"必须显式带上,否则芯片/面板只能显示一个无法归属的状态。
1586
+ */
1587
+ bookName?: string
848
1588
  /** 区间起点(含)。 */
849
1589
  startNo: number
850
1590
  /** 区间终点(含)。 */
@@ -950,13 +1690,15 @@ export type JobFrame =
950
1690
  | { type: 'start'; no: number; title: string }
951
1691
  | { type: 'delta'; text: string }
952
1692
  | { type: 'progress'; chars: number }
953
- | { type: 'done'; no: number; file: string; chars: number; title: string }
1693
+ | { type: 'done'; no: number; file: string; chars: number; title: string; warn?: string }
954
1694
  | { type: 'review'; no: number; report: ReviewReport }
955
1695
  | { type: 'author-review'; no: number; review: AuthorReview }
956
1696
  | { type: 'author-backfill-done'; count: number }
957
1697
  | { type: 'rewritten'; no: number; file: string; chars: number }
958
1698
  /** 润色/重写完成,产物作为待确认草稿(尚未覆盖正文)。 */
959
1699
  | { type: 'drafted'; no: number; chars: number; draft: string }
1700
+ | { type: 'outline-progress'; done: number; total: number; phase: string }
1701
+ | { type: 'outline-done'; outline: string; chars: number }
960
1702
  | { type: 'error'; no: number; message: string }
961
1703
 
962
1704
  /** POST /review request: review one written chapter. */
@@ -1017,13 +1759,41 @@ export interface ChapterResponse {
1017
1759
  }
1018
1760
 
1019
1761
  /** POST /export request/response. */
1762
+ /**
1763
+ * 导出范围:
1764
+ * - `book` 整本正文(txt / md)
1765
+ * - `settings` 项目设定(总纲 / 道藏 / 大世界 / 写作资产 / 卷首语)
1766
+ * - `plan` 规划(卷计划 + 章节计划,含每章目标/要点/钩子/硬事实)
1767
+ * - `characters` 角色(角色库 + 人物志当前状态)
1768
+ * - `review` 质检记录(逐章审稿 + 作者复盘 + 伏笔/剧情线状态)
1769
+ * - `project` 项目 JSON(完整状态,用于备份/迁移;仅 json 格式)
1770
+ */
1771
+ export type ExportScope = 'book' | 'settings' | 'plan' | 'characters' | 'review' | 'project'
1772
+
1773
+ /** 导出范围全集(宿主校验用;顺序即 UI 展示顺序)。 */
1774
+ export const EXPORT_SCOPE_VALUES: readonly ExportScope[] = ['book', 'settings', 'plan', 'characters', 'review', 'project']
1775
+
1776
+ /** 导出范围的中文标签。 */
1777
+ export const EXPORT_SCOPE_LABELS: Record<ExportScope, string> = {
1778
+ book: '整本正文',
1779
+ settings: '项目设定',
1780
+ plan: '规划(卷/章节)',
1781
+ characters: '角色',
1782
+ review: '质检记录',
1783
+ project: '项目备份 JSON',
1784
+ }
1785
+
1020
1786
  export interface ExportRequest {
1021
- format: 'txt' | 'md'
1787
+ format: 'txt' | 'md' | 'json'
1788
+ /** 缺省 `book`(兼容旧调用)。 */
1789
+ scope?: ExportScope
1022
1790
  }
1023
1791
  export interface ExportResponse {
1024
1792
  file: string
1025
1793
  chars: number
1026
1794
  chapters: number
1795
+ scope: ExportScope
1796
+ format: 'txt' | 'md' | 'json'
1027
1797
  }
1028
1798
 
1029
1799
  /** POST /config request: patch any subset of the runtime config. */
@@ -1032,16 +1802,30 @@ export interface ConfigPatch {
1032
1802
  outputDir?: string
1033
1803
  provider?: string
1034
1804
  model?: string
1805
+ generateModel?: string
1806
+ reviewModel?: string
1807
+ auditModel?: string
1808
+ /** 备用模型(主模型失败时自动切换重试一次;空串 = 关闭)。 */
1809
+ fallbackModel?: string
1810
+ /** 出章后自动抽取故事时间线(默认开)。 */
1811
+ autoTimeline?: boolean
1035
1812
  reasoningEffort?: 'off' | 'low' | 'high' | 'max'
1813
+ analysisReasoning?: 'off' | 'low' | 'high' | 'max'
1036
1814
  chapterChars?: number
1037
1815
  maxTokens?: number
1038
1816
  reviewPassScore?: number
1039
1817
  autoReview?: boolean
1040
1818
  autoAuthorReview?: boolean
1041
1819
  autoReviewAfterRevise?: boolean
1042
- imageApiKey?: string
1043
- imageApiModel?: string
1044
- imageApiEnabled?: boolean
1820
+ /** 自定义背景图(URL / dataURL / 服务端路径引用)。 */
1821
+ themeBackground?: string
1822
+ /** 自定义背景遮罩/模糊强度 0-80。 */
1823
+ themeBackgroundBlur?: number
1824
+ /** 玻璃透明度 0-100(100=当前原样)。 */
1825
+ themeOpacity?: number
1826
+ enableAdaptMode?: boolean
1827
+ /** 手动添加的模型库(完整替换保存)。 */
1828
+ savedModels?: SavedModel[]
1045
1829
  }
1046
1830
 
1047
1831
  // ------------------------------------------------------------ assistant
@@ -1068,6 +1852,8 @@ export type AssistantFrame =
1068
1852
  | { type: 'tool'; name: string; status: 'start' | 'done' | 'error'; detail?: string }
1069
1853
  /** Live output while a tool runs (e.g. chapter text being generated). */
1070
1854
  | { type: 'toolDelta'; name: string; text: string }
1855
+ /** 工具完整结果(供前端渲染成结构化卡片,如拆书/导演)。 */
1856
+ | { type: 'toolResult'; name: string; text: string }
1071
1857
  | { type: 'done' }
1072
1858
  | { type: 'error'; message: string }
1073
1859
 
@@ -1080,16 +1866,22 @@ export interface AssistantHistoryResponse {
1080
1866
 
1081
1867
  /** 题材基底库:一本书属于哪个阅读市场。树形(题材→子题材→下级)。 */
1082
1868
  export interface GenreNode {
1869
+ /** 稳定标识(内置库交叉引用)。 */
1870
+ id?: string
1083
1871
  /** 题材名称(标签,如「仙侠修真」「都市异能」)。 */
1084
1872
  name: string
1085
1873
  /** 题材特征、常见爽点、叙事重心或读者期待。 */
1086
1874
  description: string
1875
+ /** 该题材的写法指引(开书定盘/卷计划用,区别于「读者期待」)。 */
1876
+ template?: string
1087
1877
  /** 子题材。 */
1088
1878
  children: GenreNode[]
1089
1879
  }
1090
1880
 
1091
1881
  /** 推进模式库:读者为什么继续看下一章。 */
1092
1882
  export interface ProgressionMode {
1883
+ /** 稳定标识(与内置库交叉引用)。 */
1884
+ key?: string
1093
1885
  /** 模式名称(如「升级变强」「经营扩张」「解谜揭露」)。 */
1094
1886
  name: string
1095
1887
  /** 核心驱动力:靠什么制造追读动力。 */
@@ -1102,12 +1894,34 @@ export interface ProgressionMode {
1102
1894
  risks: string[]
1103
1895
  /** 主模式或辅助模式。 */
1104
1896
  primary: boolean
1897
+ /** 该模式的写法指引(开书定盘/卷计划用)。 */
1898
+ template?: string
1899
+ /** 推进单位序列(每章如何推进,如「立威→打破质疑→扩大影响→碾压」)。 */
1900
+ progressionUnits?: string[]
1901
+ /** 允许出现的冲突形态。 */
1902
+ allowedConflictForms?: string[]
1903
+ /** 应避免的冲突形态(跑偏信号)。 */
1904
+ forbiddenConflictForms?: string[]
1905
+ /** 冲突烈度上限(low/medium/high),用于卷/章计划和审稿对齐。 */
1906
+ conflictCeiling?: 'low' | 'medium' | 'high'
1907
+ /** 单章推进单位说明。 */
1908
+ chapterUnit?: string
1909
+ /** 卷末应兑现的回报。 */
1910
+ volumeReward?: string
1911
+ /** 主驱动必须持续出现的信号(读者期待确认)。 */
1912
+ mandatorySignals?: string[]
1913
+ /** 反信号:出现即跑偏。 */
1914
+ antiSignals?: string[]
1915
+ /** 优先用的问题解决方式。 */
1916
+ resolutionStyle?: string
1105
1917
  }
1106
1918
 
1107
1919
  /** 反 AI 规则:一条「要避免的问题 + 修正方向」。 */
1108
1920
  export interface AntiAiRule {
1109
1921
  /** 规则名(如「禁止解释型心理描写」「AI 高频套话」)。 */
1110
1922
  name: string
1923
+ /** 稳定标识(与 defaultAntiAiRuleKeys 交叉引用;缺省用 name)。 */
1924
+ key?: string
1111
1925
  /** 要避免的表达问题,具体可检查。 */
1112
1926
  avoid: string
1113
1927
  /** 推荐修正方向。 */
@@ -1116,9 +1930,60 @@ export interface AntiAiRule {
1116
1930
  detectPatterns?: string[]
1117
1931
  /** 是否内置全局规则(内置规则随插件发布,项目规则为用户自定义)。 */
1118
1932
  builtin?: boolean
1933
+ /** 规则类别:forbidden=禁止类(命中即问题)/ risk=风险类(需注意但不硬伤)/ encourage=鼓励类(不命中不算错,只作建议)。 */
1934
+ severity?: 'forbidden' | 'risk' | 'encourage'
1935
+ /** 问题严重度(用于审稿优先级;缺省按类别推断)。 */
1936
+ riskLevel?: 'low' | 'medium' | 'high'
1937
+ /** 生成时直接注入的约束指令(缺失时回退到 avoid)。 */
1938
+ promptInstruction?: string
1939
+ /** 是否允许自动改写(risk 类通常 false)。 */
1940
+ autoRewrite?: boolean
1941
+ /** 是否为全局基线规则(新书默认启用,防止规则丢失后降级)。 */
1942
+ globalBaselineEnabled?: boolean
1943
+ /** 是否启用(缺省 true)。 */
1944
+ enabled?: boolean
1945
+ /** 作用域(缺省 all)。 */
1946
+ scope?: Array<'writing' | 'review' | 'polish' | 'all'>
1947
+ }
1948
+
1949
+ /** 预置叙事风格模板(一键绑定无需样本文本)。 */
1950
+ export interface StyleTemplateNarrativeRules {
1951
+ progressionMode?: string
1952
+ sceneUnitPattern?: string[]
1953
+ multiPov?: boolean
1954
+ looping?: boolean
1955
+ endingStyle?: string
1956
+ povSwitchStyle?: string
1957
+ summary?: string
1958
+ }
1959
+
1960
+ export interface StyleTemplateCharacterRules {
1961
+ allowSelfReflection?: boolean
1962
+ emotionExpression?: string
1963
+ defenseMechanisms?: string[]
1964
+ facePriority?: boolean
1965
+ dialogueStyle?: string
1966
+ summary?: string
1967
+ }
1968
+
1969
+ export interface StyleTemplateLanguageRules {
1970
+ register?: string
1971
+ roughness?: number
1972
+ allowIncompleteSentences?: boolean
1973
+ allowSwearing?: boolean
1974
+ sentenceVariation?: string
1975
+ allowUselessDetails?: boolean
1976
+ summary?: string
1977
+ }
1978
+
1979
+ export interface StyleTemplateRhythmRules {
1980
+ pace?: string
1981
+ paragraphDensity?: string
1982
+ allowFragmentedFlow?: boolean
1983
+ actionOverExplanation?: boolean
1984
+ summary?: string
1119
1985
  }
1120
1986
 
1121
- /** 预置写法模板(来自 AI-Novel-Writing-Assistant 内置数据,一键绑定无需样本文本)。 */
1122
1987
  export interface StyleTemplate {
1123
1988
  /** 模板 key(如 power-up-escalation)。 */
1124
1989
  key: string
@@ -1130,18 +1995,66 @@ export interface StyleTemplate {
1130
1995
  category: string
1131
1996
  /** 适用题材。 */
1132
1997
  applicableGenres: string[]
1133
- /** 叙述规则。 */
1998
+ /** 标签(便于筛选)。 */
1999
+ tags?: string[]
2000
+ /** 一句话分析(模板定位说明)。 */
2001
+ analysisMarkdown?: string
2002
+ /** 叙述规则(结构化)。 */
2003
+ narrative?: StyleTemplateNarrativeRules
2004
+ /** 角色规则(结构化)。 */
2005
+ character?: StyleTemplateCharacterRules
2006
+ /** 语言规则(结构化)。 */
2007
+ language?: StyleTemplateLanguageRules
2008
+ /** 节奏规则(结构化)。 */
2009
+ rhythm?: StyleTemplateRhythmRules
2010
+ /** 叙述规则(扁平,兼容旧数据)。 */
1134
2011
  proseRules: string[]
1135
- /** 角色/台词规则。 */
2012
+ /** 角色/台词规则(扁平,兼容旧数据)。 */
1136
2013
  dialogueRules: string[]
1137
- /** 语言规则。 */
2014
+ /** 语言规则(扁平,兼容旧数据)。 */
1138
2015
  languageRules: string[]
1139
- /** 节奏规则。 */
2016
+ /** 节奏规则(扁平,兼容旧数据)。 */
1140
2017
  rhythmRules: string[]
1141
2018
  /** 该模板默认绑定的反 AI 规则 key(内置规则名)。 */
1142
2019
  defaultAntiAiRuleKeys: string[]
1143
2020
  }
1144
2021
 
2022
+ /** 起始风格画像:无样本文本也能快速绑定一套写法。 */
2023
+ export interface StarterStyleProfile {
2024
+ /** stable key(如 starter-power-up)。 */
2025
+ key: string
2026
+ /** 绑定到的写法模板 key。 */
2027
+ templateKey: string
2028
+ /** 画像名。 */
2029
+ name: string
2030
+ /** 画像说明。 */
2031
+ description: string
2032
+ }
2033
+
2034
+ /** 剧情桥段库:可复用的情节套路/桥段(作者阅读经验沉淀,与书内 Plotline 不同层)。 */
2035
+ export interface PlotBeatTemplate {
2036
+ /** 模板 key(如 face-slap / exit-wedding)。 */
2037
+ key: string
2038
+ /** 桥段名(如「打脸」「退婚」)。 */
2039
+ name: string
2040
+ /** 分类(如「装逼打脸」「身份逆袭」)。 */
2041
+ category: string
2042
+ /** 一句话说明。 */
2043
+ summary: string
2044
+ /** 适用位置(开局/前期/中期/后期/高潮/结尾)。 */
2045
+ position: string
2046
+ /** 前置条件。 */
2047
+ preconditions: string[]
2048
+ /** 爽点来源。 */
2049
+ payoffSource: string[]
2050
+ /** 常用组合(可搭配的桥段)。 */
2051
+ combos: string[]
2052
+ /** 禁忌(别用烂/别用死)。 */
2053
+ taboos: string[]
2054
+ /** 适用题材。 */
2055
+ applicableGenres: string[]
2056
+ }
2057
+
1145
2058
  /** 写法引擎:从样本文本提取的叙事风格资产。 */
1146
2059
  export interface StyleAsset {
1147
2060
  /** 资产名(如「林越式痞坏」「冷峻猎手风」)。 */
@@ -1156,6 +2069,32 @@ export interface StyleAsset {
1156
2069
  boundaries: string[]
1157
2070
  /** 来源样本文本(可空)。 */
1158
2071
  sourceText?: string
2072
+ /** 仿写预设:imitate=高保真仿写 / balanced=平衡 / transfer=迁移(去指纹)。 */
2073
+ preset?: 'imitate' | 'balanced' | 'transfer'
2074
+ /** 指纹风险:仿写时照搬原作独特表达的风险。 */
2075
+ fingerprintRisk?: 'low' | 'medium' | 'high'
2076
+ /** 净化后的写作指引(可安全用于生成,去掉了会暴露来源的具体细节)。 */
2077
+ writingGuidance?: string[]
2078
+ /** 禁止照搬的原作特有实体(人名/地名/核心设定句式),生成时需避开。 */
2079
+ forbiddenEntities?: string[]
2080
+ /** 创建时间。 */
2081
+ createdAt: string
2082
+ }
2083
+
2084
+ /** 写作公式(从样本文本分层提取的"这套文怎么写"浓缩,供生成/改写复用)。 */
2085
+ export interface StyleFormula {
2086
+ /** 稳定 key。 */
2087
+ key: string
2088
+ /** 公式名。 */
2089
+ name: string
2090
+ /** 提取深度:basic=骨架 / standard=完整 / deep=逐句细化。 */
2091
+ depth: 'basic' | 'standard' | 'deep'
2092
+ /** 重点聚焦域(如 开场/对话/节奏/爽点密度)。 */
2093
+ focusAreas: string[]
2094
+ /** 公式正文(Markdown)。 */
2095
+ formula: string
2096
+ /** 应用指引(生成/改写时如何套用)。 */
2097
+ applyGuidance: string
1159
2098
  /** 创建时间。 */
1160
2099
  createdAt: string
1161
2100
  }
@@ -1172,6 +2111,8 @@ export interface ProjectAssets {
1172
2111
  antiAiRules: AntiAiRule[]
1173
2112
  /** 绑定的写法资产。 */
1174
2113
  styleAssets: StyleAsset[]
2114
+ /** 写作公式(分层提取:basic/standard/deep)。 */
2115
+ styleFormulas?: StyleFormula[]
1175
2116
  /** 资产更新时间。 */
1176
2117
  updatedAt?: string
1177
2118
  }
@@ -1187,6 +2128,10 @@ export interface AssetsResponse {
1187
2128
  styleTemplates: StyleTemplate[]
1188
2129
  /** 内置推进模式候选。 */
1189
2130
  progressionLibrary: ProgressionMode[]
2131
+ /** 起始风格画像(无样本文本快速绑定写法)。 */
2132
+ starterStyleProfiles: StarterStyleProfile[]
2133
+ /** 内置剧情桥段库(可复用套路)。 */
2134
+ plotBeatLibrary: PlotBeatTemplate[]
1190
2135
  }
1191
2136
 
1192
2137
  /** POST /assets request:更新项目写作资产(部分字段可选)。 */
@@ -1196,6 +2141,7 @@ export interface AssetsPatch {
1196
2141
  auxiliaryProgressions?: ProgressionMode[]
1197
2142
  antiAiRules?: AntiAiRule[]
1198
2143
  styleAssets?: StyleAsset[]
2144
+ styleFormulas?: StyleFormula[]
1199
2145
  }
1200
2146
 
1201
2147
  /** POST /style-engine request:从样本文本提取写法资产。 */
@@ -1205,3 +2151,287 @@ export interface StyleEngineRequest {
1205
2151
  /** 资产名(可选,默认「风格资产 N」)。 */
1206
2152
  name?: string
1207
2153
  }
2154
+
2155
+ // ---------------------------------------------------------- author assets (总数据)
2156
+
2157
+ /** 作者资产库中一条可跨书复用的资产(笔法/红线/套路/角色模板/世界观模板等)。 */
2158
+ export interface AuthorStyleAsset {
2159
+ /** 稳定 id(本地唯一)。 */
2160
+ id: string
2161
+ /** 资产名(如「短句快节奏爽文风」「林越式痞坏角色」)。 */
2162
+ name: string
2163
+ /** 资产类型。 */
2164
+ kind: 'style' | 'antiAi' | 'progression' | 'genre' | 'roleTemplate' | 'worldTemplate' | 'plotBeat' | 'custom'
2165
+ /** 一句话摘要。 */
2166
+ summary: string
2167
+ /** 资产正文内容(按 kind 约定解读的文本/JSON 描述)。 */
2168
+ content: string
2169
+ /** 结构化载荷(角色模板/世界观模板等可结构化字段;缺省为 null)。 */
2170
+ structured?: Record<string, unknown>
2171
+ /** 来源书名(哪本书提炼/收藏而来)。 */
2172
+ sourceBooks: string[]
2173
+ /** 标签。 */
2174
+ tags: string[]
2175
+ /** 来源样本文本(可选)。 */
2176
+ sourceText?: string
2177
+ /** 创建时间。 */
2178
+ createdAt: string
2179
+ /** 更新时间。 */
2180
+ updatedAt: string
2181
+ }
2182
+
2183
+ /** 作者资产库(跨书总数据):按作者维度聚合的可复用资产。 */
2184
+ export interface AuthorAssetLibrary {
2185
+ /** 货架版本,便于未来迁移。 */
2186
+ version: 1
2187
+ items: AuthorStyleAsset[]
2188
+ }
2189
+
2190
+ /** GET /author-assets 响应。 */
2191
+ export interface AuthorAssetsResponse {
2192
+ assets: AuthorAssetLibrary
2193
+ }
2194
+
2195
+ /** POST /author-assets/upsert 请求:新增或按 id 更新一条资产。 */
2196
+ export interface AuthorAssetUpsertRequest {
2197
+ asset: AuthorStyleAsset
2198
+ }
2199
+
2200
+ /** POST /author-assets/remove 请求:删除一条资产。 */
2201
+ export interface AuthorAssetRemoveRequest {
2202
+ id: string
2203
+ }
2204
+
2205
+ // ---------------------------------------------------------- adaptation (改编模式)
2206
+
2207
+ /** 改编可改范围的单个维度(矩阵的一行)。 */
2208
+ export interface AdaptationDimension {
2209
+ /** 维度 key(如 realm/name/goldenFinger…)。 */
2210
+ key: string
2211
+ /** 维度名(如「大世界」「修为体系」「主角名」「金手指」)。 */
2212
+ title: string
2213
+ /** 可改度:保留 / 可改影响大 / 可改影响小 / 可自由改 / 仅视觉包装。 */
2214
+ mutability: 'locked' | 'big' | 'small' | 'free' | 'visual'
2215
+ /** 原文当前值(从正文提炼,附证据)。 */
2216
+ current: string
2217
+ /** 该值在正文中的出现证据(章节/频次,可空)。 */
2218
+ evidence?: string
2219
+ /** 建议的候选新值(可空,每套含名称与一句话说明)。 */
2220
+ candidates?: Array<{ name: string; desc?: string }>
2221
+ /** 联动影响说明(改了会影响哪些章节/角色/伏笔/术语)。 */
2222
+ impact: string
2223
+ /** 风险评级。 */
2224
+ risk: 'high' | 'medium' | 'low'
2225
+ }
2226
+
2227
+ /** POST /adapt/analyze 请求:上传全文做改编分析。 */
2228
+ export interface AdaptAnalyzeRequest {
2229
+ /** 全文文本(优先)。 */
2230
+ text: string
2231
+ /** 或服务器端全文文件路径。 */
2232
+ filePath?: string
2233
+ }
2234
+
2235
+ /** POST /adapt/analyze 响应。 */
2236
+ export interface AdaptAnalyzeResponse {
2237
+ /** 识别书名(文件名推断或正文首行)。 */
2238
+ bookName: string
2239
+ /** 拆出的章节数。 */
2240
+ chapters: number
2241
+ /** 反推的初始大纲(可空)。 */
2242
+ outline?: string
2243
+ /** 可改范围矩阵。 */
2244
+ dimensions: AdaptationDimension[]
2245
+ /** 分析消耗说明。 */
2246
+ note?: string
2247
+ }
2248
+
2249
+ /** 一条改编映射(原值 → 新值)。 */
2250
+ export interface AdaptationMapping {
2251
+ /** 原值(如「林尘」「练气」「青云宗」)。 */
2252
+ source: string
2253
+ /** 新值(如「楚风」「凝元」「天渊阁」)。 */
2254
+ target: string
2255
+ /** 适用范围。 */
2256
+ scope: 'name' | 'realm' | 'faction' | 'term' | 'other'
2257
+ /** 说明(可空)。 */
2258
+ note?: string
2259
+ }
2260
+
2261
+ /** 改编规则:哪些必须保留、哪些允许改、一致性约束。 */
2262
+ export interface AdaptationRules {
2263
+ /** 必须保留的要素(骨架/人物动机/伏笔逻辑/爽点结构…)。 */
2264
+ preserve: string[]
2265
+ /** 允许改变的要素。 */
2266
+ change: string[]
2267
+ /** 改编红线/一致性要求。 */
2268
+ constraints: string[]
2269
+ }
2270
+
2271
+ /** 一组改编方案(映射表 + 规则 + 联动影响清单)。 */
2272
+ export interface AdaptationProposal {
2273
+ /** 映射表(原→新)。 */
2274
+ mappings: AdaptationMapping[]
2275
+ /** 改编规则。 */
2276
+ rules: AdaptationRules
2277
+ /** 联动影响清单。 */
2278
+ impacts: Array<{ item: string; detail: string; risk: 'high' | 'medium' | 'low'; chapters?: number[] }>
2279
+ }
2280
+
2281
+ /** POST /adapt/propose 请求:由用户勾选的维度 + 新值生成改编方案。 */
2282
+ export interface AdaptProposeRequest {
2283
+ /** 原文全文(复用,便于 LLM 核对联动影响)。 */
2284
+ text: string
2285
+ /** 用户确认要改的维度(含原值与新值)。 */
2286
+ selections: Array<{ key: string; title: string; current: string; target: string; mutability: string }>
2287
+ /** 若已分析过,可携带完整矩阵作为上下文。 */
2288
+ dimensions?: AdaptationDimension[]
2289
+ }
2290
+
2291
+ /** POST /adapt/propose 响应。 */
2292
+ export interface AdaptProposeResponse {
2293
+ proposal: AdaptationProposal
2294
+ }
2295
+
2296
+ /** POST /adapt/execute 请求:执行改编(replace=术语替换;rewrite=逐章 LLM 重写)。 */
2297
+ export interface AdaptExecuteRequest {
2298
+ /** 原文全文。 */
2299
+ text: string
2300
+ /** 改编映射表。 */
2301
+ mappings: AdaptationMapping[]
2302
+ /** 改编规则(rewrite 模式生效:保留/允许变/红线)。 */
2303
+ rules?: AdaptationRules
2304
+ /** 执行模式:replace(术语替换)或 rewrite(逐章重写)。 */
2305
+ mode?: 'replace' | 'rewrite'
2306
+ /** rewrite 模式:只重写前 N 章(0/缺省 = 全部,且在 startNo/endNo 窗口内)。 */
2307
+ maxChapters?: number
2308
+ /** rewrite 模式:起始章号(含,默认 1)。 */
2309
+ startNo?: number
2310
+ /** rewrite 模式:结束章号(含;0/缺省 = 到全书末尾)。 */
2311
+ endNo?: number
2312
+ }
2313
+
2314
+ /** POST /adapt/execute 响应。 */
2315
+ export interface AdaptExecuteResponse {
2316
+ /** 改编后的全文。 */
2317
+ adaptedText: string
2318
+ /** 执行的映射数。 */
2319
+ mappings: number
2320
+ /** 命中统计:每条映射的替换次数。 */
2321
+ hits: Array<{ source: string; target: string; count: number }>
2322
+ /** 执行模式(replace / rewrite)。 */
2323
+ mode?: 'replace' | 'rewrite'
2324
+ /** rewrite 模式的逐章结果(no/title/chars)。 */
2325
+ rewritten?: Array<{ no: number; title: string; chars: number }>
2326
+ /** rewrite 模式下重写失败、保留原章的章节号。 */
2327
+ skipped?: number[]
2328
+ }
2329
+
2330
+ /** POST /adapt/rewrite-stream 的 NDJSON 帧(逐章进度 + 结束结果)。 */
2331
+ export type AdaptRewriteFrame =
2332
+ | { type: 'progress'; completed: number; total: number; no: number; title: string }
2333
+ | { type: 'done'; result: AdaptExecuteResponse }
2334
+ | { type: 'error'; message: string }
2335
+
2336
+ /** POST /adapt/save 请求:保存改编全文为新书(原书保留,登记书架)。 */
2337
+ export interface AdaptSaveRequest {
2338
+ /** 改编后的全文。 */
2339
+ text: string
2340
+ /** 新书名(缺省为「改编新书」;建议用「<原著>·改编版」)。 */
2341
+ bookName?: string
2342
+ /** 新书输出目录(缺省 ~/.dsh/novels/书名)。 */
2343
+ outputDir?: string
2344
+ /** 可附带反推大纲(写进新项目,便于后续续写/编辑)。 */
2345
+ outline?: string
2346
+ }
2347
+
2348
+ /** POST /adapt/save 响应。 */
2349
+ export interface AdaptSaveResponse {
2350
+ /** 登记后的书架条目。 */
2351
+ book: BookEntry
2352
+ /** 新书名。 */
2353
+ bookName: string
2354
+ /** 成功拆出的章节数。 */
2355
+ chapters: number
2356
+ /** 因内容过短被跳过的章节标题列表。 */
2357
+ skipped: string[]
2358
+ /** 新书输出目录。 */
2359
+ outputDir: string
2360
+ }
2361
+
2362
+ /** POST /adapt/materialize 请求:从源全文 + 用户编辑后的改编方案,提炼新书资料并保存为「待写新书」。 */
2363
+ export interface AdaptMaterializeRequest {
2364
+ /** 源书全文。 */
2365
+ text: string
2366
+ /** 新书名(缺省为「<源书名>·改编版」)。 */
2367
+ bookName?: string
2368
+ /** 新书输出目录(缺省 ~/.dsh/novels/书名)。 */
2369
+ outputDir?: string
2370
+ /** 反推大纲(来自分析;缺少时用源文章题兜底)。 */
2371
+ outline?: string
2372
+ /** 用户编辑后的改编方案(映射表 + 规则)。 */
2373
+ proposal: AdaptationProposal
2374
+ /** 拟规划章节数(缺省 30,可在前端调整)。 */
2375
+ chapterCount?: number
2376
+ }
2377
+
2378
+ /** POST /adapt/materialize 响应:提炼后的新书资料(预览,尚未落盘;保存走 /adapt/materialize-save)。 */
2379
+ export interface AdaptMaterializeResponse {
2380
+ /** 书架条目(仅在已保存时存在;预览阶段为 undefined)。 */
2381
+ book?: BookEntry
2382
+ /** 新书名。 */
2383
+ bookName: string
2384
+ /** 改编后总纲。 */
2385
+ outline: string
2386
+ /** 改编后道藏。 */
2387
+ bible: StoryBible
2388
+ /** 改编后角色库。 */
2389
+ roles: RoleRecord[]
2390
+ /** 改编后大世界。 */
2391
+ world: WorldState
2392
+ /** 改编后卷计划。 */
2393
+ volumes: Volume[]
2394
+ /** 改编后章节计划(status=pending)。 */
2395
+ chapters: ChapterPlan[]
2396
+ /** 新书输出目录。 */
2397
+ outputDir: string
2398
+ }
2399
+
2400
+ /** POST /adapt/materialize-save 请求:把预览/微调后的新书资料写入并登记书架。 */
2401
+ export interface AdaptMaterializeSaveRequest {
2402
+ /** 新书名(缺省为「改编版」)。 */
2403
+ bookName?: string
2404
+ /** 新书输出目录(缺省 ~/.dsh/novels/书名)。 */
2405
+ outputDir?: string
2406
+ /** 改编后总纲。 */
2407
+ outline: string
2408
+ /** 改编后道藏。 */
2409
+ bible: StoryBible
2410
+ /** 改编后角色库。 */
2411
+ roles: RoleRecord[]
2412
+ /** 改编后大世界。 */
2413
+ world: WorldState
2414
+ /** 改编后卷计划。 */
2415
+ volumes: Volume[]
2416
+ /** 改编后章节计划(status=pending)。 */
2417
+ chapters: ChapterPlan[]
2418
+ }
2419
+
2420
+ /** POST /adapt/materialize-save 响应。 */
2421
+ export interface AdaptMaterializeSaveResponse {
2422
+ /** 登记后的书架条目。 */
2423
+ book: BookEntry
2424
+ /** 新书名。 */
2425
+ bookName: string
2426
+ /** 成功写入的章节数。 */
2427
+ chapters: number
2428
+ /** 新书输出目录。 */
2429
+ outputDir: string
2430
+ }
2431
+
2432
+ /** POST /plugin/update 响应:插件自更新结果。 */
2433
+ export interface PluginUpdateResponse {
2434
+ ok: boolean
2435
+ /** 更新结果说明(成功/失败/环境提示)。 */
2436
+ message: string
2437
+ }