@waterwx/dsh-novel-forge 1.2.0 → 1.3.0-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 (141) hide show
  1. package/README.md +236 -349
  2. package/lib/client.js +56064 -10565
  3. package/lib/index.js +13922 -5218
  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 +178 -10
  11. package/lib/types/client/docx.d.ts +2 -0
  12. package/lib/types/client/index.d.ts +1 -1
  13. package/lib/types/client/llmLive.d.ts +31 -0
  14. package/lib/types/client/locales.d.ts +28 -11
  15. package/lib/types/client/panel/AdaptModeView.d.ts +5 -0
  16. package/lib/types/client/panel/AiTag.d.ts +1 -0
  17. package/lib/types/client/panel/AssistantTab.d.ts +4 -1
  18. package/lib/types/client/panel/AuthorAssetsView.d.ts +4 -0
  19. package/lib/types/client/panel/AuthorHome.d.ts +34 -0
  20. package/lib/types/client/panel/BookAnalysisView.d.ts +4 -0
  21. package/lib/types/client/panel/CmdPalette.d.ts +12 -0
  22. package/lib/types/client/panel/CreateBookView.d.ts +5 -1
  23. package/lib/types/client/panel/DirectorView.d.ts +7 -0
  24. package/lib/types/client/panel/GlobalAssetLibraryView.d.ts +4 -0
  25. package/lib/types/client/panel/IdeaInspirationView.d.ts +6 -0
  26. package/lib/types/client/panel/ImportModal.d.ts +7 -0
  27. package/lib/types/client/panel/KnowledgeBaseView.d.ts +4 -0
  28. package/lib/types/client/panel/LiveFeedLog.d.ts +13 -0
  29. package/lib/types/client/panel/MarketRadarView.d.ts +5 -0
  30. package/lib/types/client/panel/ModelManager.d.ts +14 -0
  31. package/lib/types/client/panel/NovelPanel.d.ts +6 -1
  32. package/lib/types/client/panel/PageHeader.d.ts +18 -0
  33. package/lib/types/client/panel/ProgressConsole.d.ts +17 -0
  34. package/lib/types/client/panel/ProgressHomeView.d.ts +5 -0
  35. package/lib/types/client/panel/PromptSlotsView.d.ts +11 -0
  36. package/lib/types/client/panel/ReasoningSection.d.ts +10 -0
  37. package/lib/types/client/panel/SettingsView.d.ts +19 -0
  38. package/lib/types/client/panel/ShelfView.d.ts +12 -1
  39. package/lib/types/client/panel/SubPage.d.ts +27 -0
  40. package/lib/types/client/panel/TensionView.d.ts +14 -0
  41. package/lib/types/client/panel/TimelineView.d.ts +14 -0
  42. package/lib/types/client/panel/toast.d.ts +2 -0
  43. package/lib/types/client/panel/views.d.ts +25 -7
  44. package/lib/types/client/run-status.d.ts +19 -0
  45. package/lib/types/client/text.d.ts +9 -0
  46. package/lib/types/docx-core.d.ts +16 -0
  47. package/lib/types/docx.d.ts +2 -3
  48. package/lib/types/engine.d.ts +185 -41
  49. package/lib/types/global-assets.d.ts +6 -0
  50. package/lib/types/index.d.ts +22 -2
  51. package/lib/types/llm-live.d.ts +75 -0
  52. package/lib/types/llm-retry.d.ts +38 -0
  53. package/lib/types/market-radar-scan.d.ts +19 -0
  54. package/lib/types/market-radar-sources.d.ts +31 -0
  55. package/lib/types/migrate-output.d.ts +25 -0
  56. package/lib/types/novel-context.d.ts +80 -0
  57. package/lib/types/prompt-slots.d.ts +57 -0
  58. package/lib/types/prompt-utils.d.ts +35 -0
  59. package/lib/types/prompting.d.ts +10 -0
  60. package/lib/types/protocol.d.ts +1311 -125
  61. package/lib/types/review-policy.d.ts +97 -0
  62. package/lib/types/routes.d.ts +4 -0
  63. package/lib/types/run.d.ts +3 -1
  64. package/lib/types/snapshots.d.ts +46 -0
  65. package/lib/types/stage-contract.d.ts +60 -0
  66. package/lib/types/tension.d.ts +65 -0
  67. package/lib/types/timeline.d.ts +37 -0
  68. package/package.json +52 -27
  69. package/scripts/patch-schemastery.mjs +47 -0
  70. package/src/action-guard.ts +127 -0
  71. package/src/ai-scan.ts +179 -0
  72. package/src/assets.ts +1806 -520
  73. package/src/assistant.ts +1098 -770
  74. package/src/author-assets.ts +149 -0
  75. package/src/bookshelf.ts +187 -151
  76. package/src/client/api.ts +758 -410
  77. package/src/client/docx.ts +37 -69
  78. package/src/client/index.ts +3 -1
  79. package/src/client/llmLive.ts +111 -0
  80. package/src/client/locales.ts +418 -383
  81. package/src/client/mount.tsx +1 -1
  82. package/src/client/panel/AdaptModeView.tsx +535 -0
  83. package/src/client/panel/AiTag.tsx +7 -0
  84. package/src/client/panel/AssetsTab.tsx +448 -458
  85. package/src/client/panel/AssistantTab.tsx +355 -301
  86. package/src/client/panel/AuthorAssetsView.tsx +206 -0
  87. package/src/client/panel/AuthorHome.tsx +309 -0
  88. package/src/client/panel/BookAnalysisView.tsx +63 -0
  89. package/src/client/panel/CmdPalette.tsx +102 -0
  90. package/src/client/panel/CreateBookView.tsx +366 -348
  91. package/src/client/panel/DirectorView.tsx +200 -0
  92. package/src/client/panel/GlobalAssetLibraryView.tsx +168 -0
  93. package/src/client/panel/IdeaInspirationView.tsx +76 -0
  94. package/src/client/panel/ImportModal.tsx +303 -0
  95. package/src/client/panel/KnowledgeBaseView.tsx +125 -0
  96. package/src/client/panel/LiveFeedLog.tsx +204 -0
  97. package/src/client/panel/MarketRadarView.tsx +377 -0
  98. package/src/client/panel/ModelManager.tsx +205 -0
  99. package/src/client/panel/NovelPanel.tsx +5517 -4597
  100. package/src/client/panel/PageHeader.tsx +37 -0
  101. package/src/client/panel/ProgressConsole.tsx +63 -0
  102. package/src/client/panel/PromptSlotsView.tsx +97 -0
  103. package/src/client/panel/ReaderView.tsx +306 -306
  104. package/src/client/panel/ReasoningSection.tsx +31 -0
  105. package/src/client/panel/RunPanel.tsx +223 -204
  106. package/src/client/panel/SettingsView.tsx +340 -0
  107. package/src/client/panel/ShelfView.tsx +266 -236
  108. package/src/client/panel/SubPage.tsx +42 -0
  109. package/src/client/panel/TensionView.tsx +196 -0
  110. package/src/client/panel/TimelineView.tsx +192 -0
  111. package/src/client/panel/WorldTab.tsx +202 -202
  112. package/src/client/panel/panel.module.css +5764 -2941
  113. package/src/client/panel/toast.ts +51 -0
  114. package/src/client/panel/views.tsx +401 -314
  115. package/src/client/run-status.ts +143 -0
  116. package/src/client/sidebar-entry.ts +1 -1
  117. package/src/client/text.ts +28 -0
  118. package/src/docx-core.ts +53 -0
  119. package/src/docx.ts +44 -83
  120. package/src/engine.ts +4672 -2787
  121. package/src/global-assets.ts +59 -0
  122. package/src/index.ts +323 -252
  123. package/src/llm-live.ts +260 -0
  124. package/src/llm-retry.ts +77 -0
  125. package/src/market-radar-scan.ts +41 -0
  126. package/src/market-radar-sources.ts +173 -0
  127. package/src/migrate-output.ts +76 -0
  128. package/src/novel-context.ts +286 -0
  129. package/src/prompt-slots.ts +125 -0
  130. package/src/prompting.ts +26 -0
  131. package/src/protocol.ts +2383 -1182
  132. package/src/review-policy.ts +161 -0
  133. package/src/routes.ts +3724 -2151
  134. package/src/run.ts +346 -330
  135. package/src/snapshots.ts +174 -0
  136. package/src/stage-contract.ts +189 -0
  137. package/src/tension.ts +240 -0
  138. package/src/timeline.ts +159 -0
  139. package/lib/client.js.map +0 -1
  140. package/lib/index.js.map +0 -1
  141. package/src/client/panel/BookshelfBar.tsx +0 -170
@@ -18,7 +18,7 @@ export declare const zh: {
18
18
  readonly 'tab.plan': "章节";
19
19
  readonly 'tab.bible': "道藏";
20
20
  readonly 'tab.foreshadow': "暗线";
21
- readonly 'tab.assistant': "AI 助手";
21
+ readonly 'tab.assistant': "AI 编辑 Agent";
22
22
  readonly 'tab.settings': "设置";
23
23
  readonly 'workflow.title': "创作工作台";
24
24
  readonly 'workflow.step1': "① 加载总纲";
@@ -79,7 +79,7 @@ export declare const zh: {
79
79
  readonly 'plan.volumes': "卷";
80
80
  readonly 'plan.noVolume': "未分卷";
81
81
  readonly 'bible.title': "道藏";
82
- readonly 'bible.gen': "AI 提炼道藏";
82
+ readonly 'bible.gen': "提炼道藏";
83
83
  readonly 'bible.genre': "题材基调";
84
84
  readonly 'bible.worldRules': "世界规则";
85
85
  readonly 'bible.characters': "人物志";
@@ -87,7 +87,7 @@ export declare const zh: {
87
87
  readonly 'bible.style': "风格要求";
88
88
  readonly 'bible.none': "尚未生成道藏。生成后写作会严格遵守人设与金手指规则,审稿也会按红线检查。";
89
89
  readonly 'foreshadow.title': "暗线管理";
90
- readonly 'foreshadow.suggest': "AI 建议暗线";
90
+ readonly 'foreshadow.suggest': "建议暗线";
91
91
  readonly 'foreshadow.none': "暂无暗线";
92
92
  readonly 'foreshadow.status': "状态";
93
93
  readonly 'foreshadow.planned': "计划中";
@@ -126,9 +126,9 @@ export declare const zh: {
126
126
  readonly 'plotlines.workflowTitle': "剧情线进度";
127
127
  readonly 'plotlines.workflowEmpty': "未建剧情线(去「剧情线」页创建)";
128
128
  readonly 'sensitive.title': "敏感词检查";
129
- readonly 'sensitive.scanAll': "🔞 全书敏感词检查";
129
+ readonly 'sensitive.scanAll': " 全书敏感词检查";
130
130
  readonly 'sensitive.hint': "内置违禁词库硬匹配(政治/擦边/暴力/辱骂/广告/其他),发布前建议检查;只做提示,是否修改由你判断。";
131
- readonly 'sensitive.clean': "✅ 未命中任何违禁词(扫描 {n} 章)";
131
+ readonly 'sensitive.clean': " 未命中任何违禁词(扫描 {n} 章)";
132
132
  readonly 'sensitive.hits': "命中 {n} 处({chapters} 章受影响)";
133
133
  readonly 'sensitive.goFix': "去修订";
134
134
  readonly 'sensitive.fixPrefill': "请删除或替换正文中的违禁表达「{word}」(类别:{category}),用含蓄/间接的写法替代。";
@@ -142,16 +142,33 @@ export declare const zh: {
142
142
  readonly 'settings.provider': "模型提供商";
143
143
  readonly 'settings.model': "模型";
144
144
  readonly 'settings.modelCustom': "自定义…";
145
+ readonly 'settings.customProvider': "自定义提供商…";
146
+ readonly 'settings.edit': "编辑";
147
+ readonly 'settings.delete': "删除";
145
148
  readonly 'settings.modelCustomPlaceholder': "输入任意模型 id";
146
- readonly 'settings.reasoningEffort': "思考强度 (reasoningEffort)";
149
+ readonly 'settings.savedModels': "我的模型";
150
+ readonly 'settings.modelCards': "模型卡片(内置 + 已添加)";
151
+ readonly 'settings.savedModelName': "名称";
152
+ readonly 'settings.addModel': "添加模型";
153
+ readonly 'settings.catalogRefresh': "刷新厂商";
154
+ readonly 'settings.refreshModels': "刷新模型";
155
+ readonly 'settings.savedModelsHint': "手动添加常用模型(provider + 模型 id),点击即可切换当前模型;厂商模式会写入 DSH 凭据并注册路由。";
156
+ readonly 'settings.testConnection': "测试连通";
157
+ readonly 'settings.testRunning': "测试中";
158
+ readonly 'settings.testOk': "连通";
159
+ readonly 'settings.testFail': "失败";
160
+ readonly 'settings.testHint': "真实发送一次最小调用(约几十 token),验证 Key / 端点 / 模型可用。";
161
+ readonly 'settings.reasoningSection': "推理强度";
162
+ readonly 'settings.reasoningEffort': "写作类任务思考强度 (reasoningEffort)";
163
+ readonly 'settings.reasoningHint': "章节生成/润色/重写/审稿等写作任务使用;关掉更省更快。";
164
+ readonly 'settings.analysisReasoning': "分析类任务思考强度(提炼/拆书/反推大纲)";
165
+ readonly 'settings.analysisReasoningHint': "角色/场景/道藏提炼、拆书、反推大纲等一次性分析任务默认 low,保证质量,不受上面写作档位影响。";
147
166
  readonly 'settings.reasoning.off': "off · 关闭思考(推荐日常写文)";
148
167
  readonly 'settings.reasoning.low': "low · 低思考";
149
168
  readonly 'settings.reasoning.high': "high · 高思考";
150
169
  readonly 'settings.reasoning.max': "max · 最高思考(质检/推演)";
151
- readonly 'settings.reasoningHint': "off 最快最省;high/max 更慢更贵但推理更强";
152
170
  readonly 'settings.theme': "主题";
153
171
  readonly 'settings.themeLiquid': "iOS 液态玻璃(绿)";
154
- readonly 'settings.themeClassic': "经典毛玻璃(蓝)";
155
172
  readonly 'settings.themeNeumorph': "新拟物(双阴影)";
156
173
  readonly 'settings.themeHint': "存于浏览器本地,即时生效";
157
174
  readonly 'settings.chapterChars': "每章目标字数";
@@ -178,13 +195,13 @@ export declare const zh: {
178
195
  readonly 'progress.rewriting': "正在修订第 {no} 章…";
179
196
  readonly 'progress.polishing': "正在润色第 {no} 章…";
180
197
  readonly 'progress.empty': "生成/审稿进度将显示在这里";
181
- readonly 'assistant.hint': "和 AI 编辑讨论剧情、人设、暗线;达成一致后可让它直接修改总纲、道藏、章节内容。";
198
+ readonly 'assistant.hint': "和 AI 编辑 Agent 讨论剧情、人设、暗线;达成一致后可让它直接修改总纲、道藏、章节内容。";
182
199
  readonly 'assistant.placeholder': "例如:我想让第 2 章结尾加一个悬念——墟境里传来爷爷的声音…";
183
200
  readonly 'assistant.send': "发送";
184
- readonly 'assistant.toolStart': "⚙ 执行操作:{name}…";
201
+ readonly 'assistant.toolStart': " 执行操作:{name}…";
185
202
  readonly 'assistant.toolDone': "✓ {name} 完成:{detail}";
186
203
  readonly 'assistant.toolError': "✗ {name} 失败:{detail}";
187
- readonly 'assistant.empty': "还没有对话。和 AI 编辑聊聊剧情吧。";
204
+ readonly 'assistant.empty': "还没有对话。和 AI 编辑 Agent 聊聊剧情吧。";
188
205
  readonly 'status.projectNone': "输出目录中还没有项目。请先加载大纲。";
189
206
  readonly 'status.files': "已生成文件";
190
207
  readonly 'api.error': "请求失败";
@@ -0,0 +1,5 @@
1
+ import type { NovelApi } from '../api.ts';
2
+ export declare function AdaptModeView({ api, onOpenBook }: {
3
+ api: NovelApi;
4
+ onOpenBook?: (id: string) => void;
5
+ }): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export declare function AiTag(): JSX.Element;
@@ -1,7 +1,10 @@
1
1
  import type { NovelApi } from '../api.ts';
2
+ import type { StageInfo } from '../../protocol.ts';
2
3
  /** Props. */
3
4
  export interface AssistantTabProps {
4
5
  api: NovelApi;
6
+ /** 宿主算出的创作阶段(/status.stage):让作者在同一屏看到「现在该做什么」。 */
7
+ stage?: StageInfo | null;
5
8
  }
6
9
  /** The assistant conversation tab. */
7
- export declare function AssistantTab({ api }: AssistantTabProps): import("react").JSX.Element;
10
+ export declare function AssistantTab({ api, stage }: AssistantTabProps): import("react").JSX.Element;
@@ -0,0 +1,4 @@
1
+ import type { NovelApi } from '../api.ts';
2
+ export declare function AuthorAssetsView({ api }: {
3
+ api: NovelApi;
4
+ }): import("react").JSX.Element;
@@ -0,0 +1,34 @@
1
+ import type { NovelApi } from '../api.ts';
2
+ import type { BookshelfSnapshot } from '../../protocol.ts';
3
+ import { type ProgressLine } from './ProgressConsole.tsx';
4
+ export declare function AuthorHome({ api, shelf, onOpenBook, onReadBook, onAddBook, onImportBook, onBackground, progress, busy, busyLabel, liveBar, onClearProgress, onUseIdea, themeMode, themeDensity, onToggleMode, onChangeThemeMode, onChangeThemeDensity }: {
5
+ /** 当前显示模式(顶栏「墨纸 / 纸白」切换用)。 */
6
+ themeMode?: 'system' | 'light' | 'dark';
7
+ /** 当前界面密度。 */
8
+ themeDensity?: 'comfort' | 'compact' | 'spacious';
9
+ /** 切换墨纸 / 纸白(由 NovelPanel 落 localStorage)。 */
10
+ onToggleMode?: () => void;
11
+ /** 改变全局显示模式(联动整个面板)。 */
12
+ onChangeThemeMode: (m: 'system' | 'light' | 'dark') => void;
13
+ /** 改变全局界面密度(联动整个面板)。 */
14
+ onChangeThemeDensity: (d: 'comfort' | 'compact' | 'spacious') => void;
15
+ api: NovelApi;
16
+ shelf: BookshelfSnapshot;
17
+ onOpenBook: (id: string) => void;
18
+ onReadBook: (id: string) => void;
19
+ onAddBook: () => void;
20
+ onImportBook: () => void;
21
+ /** 创意灵感 → 采纳某个灵感带入开书向导。 */
22
+ onUseIdea?: (idea: import('../../protocol.ts').IdeaInspirationResult['ideas'][number]) => void;
23
+ /** 自定义背景变化回调。 */
24
+ onBackground?: (bg: string | undefined, blur: number) => void;
25
+ /** AI 进度实时状态(与书内共享同一份)。 */
26
+ progress?: ProgressLine[];
27
+ busy?: boolean;
28
+ busyLabel?: string;
29
+ liveBar?: {
30
+ text: string;
31
+ ratio?: number;
32
+ } | null;
33
+ onClearProgress?: () => void;
34
+ }): import("react").JSX.Element;
@@ -0,0 +1,4 @@
1
+ import type { NovelApi } from '../api.ts';
2
+ export default function BookAnalysisView({ api }: {
3
+ api: NovelApi;
4
+ }): JSX.Element;
@@ -0,0 +1,12 @@
1
+ import type { ReactElement } from 'react';
2
+ export interface CmdAction {
3
+ icon: string;
4
+ label: string;
5
+ hint?: string;
6
+ run: () => void;
7
+ }
8
+ export declare function CmdPalette({ open, onClose, actions }: {
9
+ open: boolean;
10
+ onClose: () => void;
11
+ actions: CmdAction[];
12
+ }): ReactElement | null;
@@ -1,9 +1,13 @@
1
1
  import type { NovelApi } from '../api.ts';
2
2
  /** 开书向导页。 */
3
- export declare function CreateBookView({ api, onBack, onCreated, }: {
3
+ export declare function CreateBookView({ api, onBack, onCreated, initialIdea, initialName, }: {
4
4
  api: NovelApi;
5
5
  /** 返回书架。 */
6
6
  onBack: () => void;
7
7
  /** 开书成功:进入新书工作台。 */
8
8
  onCreated: (id: string) => void;
9
+ /** 从「创意灵感」带过来的起步想法(预填到「一句话想法」输入框)。 */
10
+ initialIdea?: string;
11
+ /** 从「创意灵感」带过来的初始书名。 */
12
+ initialName?: string;
9
13
  }): import("react").JSX.Element;
@@ -0,0 +1,7 @@
1
+ import type { NovelApi } from '../api.ts';
2
+ import type { DirectorTodo } from '../../protocol.ts';
3
+ export default function DirectorView({ api, todos, onTodosChange }: {
4
+ api: NovelApi;
5
+ todos: DirectorTodo[];
6
+ onTodosChange?: (todos: DirectorTodo[]) => void;
7
+ }): JSX.Element;
@@ -0,0 +1,4 @@
1
+ import type { NovelApi } from '../api.ts';
2
+ export declare function GlobalAssetLibraryView({ api }: {
3
+ api: NovelApi;
4
+ }): import("react").JSX.Element;
@@ -0,0 +1,6 @@
1
+ import type { NovelApi } from '../api.ts';
2
+ import type { IdeaInspirationResult } from '../../protocol.ts';
3
+ export default function IdeaInspirationView({ api, onUseIdea }: {
4
+ api: NovelApi;
5
+ onUseIdea?: (idea: IdeaInspirationResult['ideas'][number]) => void;
6
+ }): JSX.Element;
@@ -0,0 +1,7 @@
1
+ import type { NovelApi } from '../api.ts';
2
+ export declare function ImportModal({ api, onClose, onImported, }: {
3
+ api: NovelApi;
4
+ onClose: () => void;
5
+ /** 导入成功并已激活该书后回调(刷新书架)。 */
6
+ onImported: () => void | Promise<void>;
7
+ }): import("react").JSX.Element;
@@ -0,0 +1,4 @@
1
+ import type { NovelApi } from '../api.ts';
2
+ export default function KnowledgeBaseView({ api }: {
3
+ api: NovelApi;
4
+ }): JSX.Element;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * 「实时调用 / LIVE」—— 内嵌到 AI 进度窗的下半区(详情层),不再独立浮窗。
3
+ * 连接 /llm-live/stream,按 LLM 调用分组展示模型实时输出。
4
+ *
5
+ * 除实时输出外,这里还承担两件与「花了多少」有关的事:
6
+ * 1) 每次调用显示 token 用量(输入↑ / 输出↓ / 思考)与耗时、首字耗时;
7
+ * 2) 「查看 Prompt」按 sessionId 拉取这次调用**实际发送**的 system / user。
8
+ * 顶部另有一条「本次运行」累计条(进程内,重启归零)。
9
+ *
10
+ * 状态色全部走 panel.module.css 的 .lfPill / .lfDot(主题令牌 + --nf-streaming),
11
+ * 不再内联硬编码色;布局性 inline style 保留(均为令牌引用或动态值)。
12
+ */
13
+ export default function LiveFeedLog(): JSX.Element;
@@ -0,0 +1,5 @@
1
+ import type { NovelApi } from '../api.ts';
2
+ export default function MarketRadarView({ api, bookId }: {
3
+ api: NovelApi;
4
+ bookId?: string;
5
+ }): JSX.Element;
@@ -0,0 +1,14 @@
1
+ import type { NovelApi } from '../api.ts';
2
+ import type { SavedModel } from '../../protocol.ts';
3
+ /** 目录不可用时回退的内置预设(对齐当前模型目录)。 */
4
+ export declare const FALLBACK_MODEL_PRESETS: readonly ["deepseek-flash", "deepseek-v4-pro", "deepseek-chat", "deepseek-reasoner"];
5
+ export interface ModelManagerProps {
6
+ api: NovelApi;
7
+ provider: string;
8
+ model: string;
9
+ savedModels: SavedModel[];
10
+ onProvider: (provider: string) => void;
11
+ onModel: (model: string) => void;
12
+ onSavedModels: (models: SavedModel[]) => void;
13
+ }
14
+ export declare function ModelManager({ api, provider, model, onProvider, onModel }: ModelManagerProps): JSX.Element;
@@ -1,7 +1,12 @@
1
1
  import type { NovelApi } from '../api.ts';
2
2
  import type { PanelController } from './controller.ts';
3
+ /**
4
+ * 面板宽度低于此值时自动折叠左侧导航。
5
+ * 依据:.panelNav 占 216px,内容区留到 ~680px 才不至于把正文挤成竖排。
6
+ * 宿主中列宽度 ≠ 视口宽度(用户可拖拽侧边栏),所以必须用实测宽度而非媒体查询。
7
+ */
3
8
  /** The panel's tab identifiers. */
4
- export type NovelTab = 'workflow' | 'overview' | 'blurb' | 'plan' | 'bible' | 'world' | 'foreshadow' | 'assistant' | 'settings' | 'characters' | 'roles' | 'facts' | 'plotlines' | 'reviews' | 'progress' | 'breakdown' | 'storyboard' | 'assetsGenre' | 'assetsProgression' | 'assetsTemplates' | 'assetsRules' | 'assetsStyle' | 'run' | 'book' | 'assets';
9
+ export type NovelTab = 'workflow' | 'overview' | 'blurb' | 'plan' | 'bible' | 'world' | 'foreshadow' | 'assistant' | 'settings' | 'characters' | 'roles' | 'facts' | 'plotlines' | 'reviews' | 'progress' | 'breakdown' | 'director' | 'knowledge' | 'assetsGenre' | 'assetsProgression' | 'assetsTemplates' | 'assetsRules' | 'assetsStyle' | 'run' | 'book' | 'assets';
5
10
  /** Panel shell props. */
6
11
  export interface NovelPanelProps {
7
12
  /** The panel state owner (open/close/toggle). */
@@ -0,0 +1,18 @@
1
+ /** 墨案统一页头:eyebrow(11 大写窄) + 衬线大标题 + 一句说明 + 主/次动作。
2
+ * 每个视图只用一个 PageHeader,消灭"各自为政"的页面标题。
3
+ * 图标用 lucide 16 (单色),标题旁禁止 emoji;标题用衬线 Display(书卷感)。 */
4
+ import type { ReactNode } from 'react';
5
+ export declare function PageHeader({ eyebrow, title, icon, sub, actions, right }: {
6
+ /** 页眉小标(大写窄,可选,如 "BOOKSHELF")。 */
7
+ eyebrow?: string;
8
+ /** 页面大标题(衬线 Display)。 */
9
+ title: string;
10
+ /** lucide 图标(单色,16px),可选。 */
11
+ icon?: ReactNode;
12
+ /** 一句话辅助说明(meta)。 */
13
+ sub?: string;
14
+ /** 右侧主/次按钮组。 */
15
+ actions?: ReactNode;
16
+ /** 标题右上(如 AI 微签)。 */
17
+ right?: ReactNode;
18
+ }): JSX.Element;
@@ -0,0 +1,17 @@
1
+ export interface ProgressLine {
2
+ id: number;
3
+ text: string;
4
+ kind: 'info' | 'done' | 'error';
5
+ live?: boolean;
6
+ ratio?: number;
7
+ }
8
+ export declare function ProgressConsole({ progress, busy, busyLabel, liveBar, onClear }: {
9
+ progress: ProgressLine[];
10
+ busy: boolean;
11
+ busyLabel: string;
12
+ liveBar: {
13
+ text: string;
14
+ ratio?: number;
15
+ } | null;
16
+ onClear: () => void;
17
+ }): import("react").JSX.Element;
@@ -0,0 +1,5 @@
1
+ import type { BookshelfSnapshot } from '../../protocol.ts';
2
+ export declare function ProgressHomeView({ shelf, onOpenBook }: {
3
+ shelf: BookshelfSnapshot;
4
+ onOpenBook: (id: string) => void;
5
+ }): import("react").JSX.Element;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * 提示词槽位:给作者留几个**安全可改**的位置来微调本书表达偏好。
3
+ *
4
+ * 边界写在界面上:槽位只**追加偏好**,不能覆盖道藏、写作红线、九条内容合规红线、
5
+ * 反 AI 规则与阶段契约 —— 这些由宿主锁定。清空即恢复默认。
6
+ */
7
+ import type { NovelApi } from '../api.ts';
8
+ export interface PromptSlotsViewProps {
9
+ api: NovelApi;
10
+ }
11
+ export default function PromptSlotsView({ api }: PromptSlotsViewProps): JSX.Element;
@@ -0,0 +1,10 @@
1
+ import type { NovelConfig } from '../../protocol.ts';
2
+ export interface ReasoningSectionProps {
3
+ reasoningEffort: NovelConfig['reasoningEffort'];
4
+ analysisReasoning: NovelConfig['analysisReasoning'];
5
+ onChange: (patch: {
6
+ reasoningEffort?: NovelConfig['reasoningEffort'];
7
+ analysisReasoning?: NovelConfig['analysisReasoning'];
8
+ }) => void;
9
+ }
10
+ export declare function ReasoningSection({ reasoningEffort, analysisReasoning, onChange }: ReasoningSectionProps): JSX.Element;
@@ -0,0 +1,19 @@
1
+ import type { NovelApi } from '../api.ts';
2
+ type SettingsTab = 'model' | 'files' | 'appearance';
3
+ export declare function SettingsView({ api, variant, onSettingsTab, onEditorFontSize, onBackground, themeMode, themeDensity, onChangeThemeMode, onChangeThemeDensity }: {
4
+ api: NovelApi;
5
+ /** page = 全屏 SubPage(保留给旧入口);drawer = 右滑抽屉内容(无壳)。 */
6
+ variant?: 'page' | 'drawer';
7
+ onSettingsTab?: (tab: SettingsTab) => void;
8
+ onEditorFontSize?: (n: number) => void;
9
+ onBackground?: (bg: string | undefined, blur: number) => void;
10
+ /** 全局显示模式(联动整个面板,NovelPanel 落 localStorage)。 */
11
+ themeMode: 'system' | 'light' | 'dark';
12
+ /** 全局界面密度。 */
13
+ themeDensity: 'comfort' | 'compact' | 'spacious';
14
+ /** 改变全局显示模式。 */
15
+ onChangeThemeMode: (m: 'system' | 'light' | 'dark') => void;
16
+ /** 改变全局界面密度。 */
17
+ onChangeThemeDensity: (d: 'comfort' | 'compact' | 'spacious') => void;
18
+ }): import("react").JSX.Element;
19
+ export {};
@@ -1,13 +1,24 @@
1
+ /**
2
+ * 书架首页视图:书卡网格(封面/书名/简介/进度)+ 搜索筛选 + 开书入口。
3
+ * 进入小说工坊默认展示;点击书卡进入该书工作台,+ 进入开书向导页。
4
+ */
5
+ import { type ReactNode } from 'react';
1
6
  import type { NovelApi } from '../api.ts';
2
7
  import type { BookshelfSnapshot } from '../../protocol.ts';
3
8
  /** 书架首页。 */
4
- export declare function ShelfView({ api, shelf, onOpenBook, onReadBook, onAddBook, }: {
9
+ export declare function ShelfView({ api, shelf, onOpenBook, onReadBook, onAddBook, onImportBook, onOpenAdapt, toolbarExtra, }: {
5
10
  api: NovelApi;
6
11
  shelf: BookshelfSnapshot;
12
+ /** 书架工具行右端插槽:组入口按钮由 AuthorHome 下放(创作 / 灵感策划 / 资产)。 */
13
+ toolbarExtra?: ReactNode;
7
14
  /** 点击书卡:激活该书并进入工作台。 */
8
15
  onOpenBook: (id: string) => void;
9
16
  /** 点击「阅读」:激活该书并进入沉浸式阅读页。 */
10
17
  onReadBook: (id: string) => void;
11
18
  /** 点击+:进入开书向导页。 */
12
19
  onAddBook: () => void;
20
+ /** 点击「导入」:打开导入弹窗(已有项目目录 / txt/md 全本)。 */
21
+ onImportBook: () => void;
22
+ /** 点击「改编模式」:进入改编六步向导(入口收在书架页头,与导入并排)。 */
23
+ onOpenAdapt?: () => void;
13
24
  }): import("react").JSX.Element;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * 统一子页骨架(1:1 对齐 demo-subpages.html 的 .subpage / .subpage-head / .subpage-body)。
3
+ *
4
+ * 所有作者级与书内子页都应套这层壳:
5
+ * - head:返回钮(可选)+ 大标题 + meta + 右侧操作区
6
+ * - body:页面内容(内部按 demo 用 .card / .box / .grid / .row 等块)
7
+ * 业务逻辑继续留在各自的 View 组件里,这里只负责「壳」。
8
+ */
9
+ import type { ReactNode } from 'react';
10
+ export declare function SubPage(props: {
11
+ /** 页面大标题(衬线 display 档)。 */
12
+ title: string;
13
+ /** 标题右侧的说明行(如「4 本书 · 当前书《X》」)。 */
14
+ meta?: ReactNode;
15
+ /** 返回钮:作者级返回书架,书内返回总编台。 */
16
+ back?: {
17
+ label: string;
18
+ onClick: () => void;
19
+ };
20
+ /** 页头右侧操作区(主 CTA 放最右)。 */
21
+ actions?: ReactNode;
22
+ /** 主题系统局部模式(透传到根 div 的 data-nf-mode,供设置页等预览明暗)。 */
23
+ dataNfMode?: 'light' | 'dark';
24
+ /** 主题系统局部密度(透传到根 div 的 data-nf-density)。 */
25
+ dataNfDensity?: 'comfort' | 'compact' | 'spacious';
26
+ children: ReactNode;
27
+ }): JSX.Element;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * 张力曲线:把「每章该有多紧」画出来并可逐章调整。
3
+ *
4
+ * 图上是三条线:
5
+ * 参考(虚线,形状预设) / 目标(实线,作者或规划设定) / 实际(散点,审稿打分)。
6
+ * 下方列出规则核对发现的曲线级问题(连续同值、高位不回落、长期低位、实际偏离目标)。
7
+ *
8
+ * 张力只影响写作提示词里的"松紧"指引,不改变任何校验规则。
9
+ */
10
+ import type { NovelApi } from '../api.ts';
11
+ export interface TensionViewProps {
12
+ api: NovelApi;
13
+ }
14
+ export default function TensionView({ api }: TensionViewProps): JSX.Element;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * 故事时间线:把逐章抽取的「时间点 / 地点 / 在场角色 / 事件」按章节顺序排开,
3
+ * 带规则初筛 + AI 复核的矛盾清单,并支持就地修正(手改后标记为 manual)。
4
+ *
5
+ * 与「编年录」的分工:编年录记事实状态,这里记**顺序**——专门抓时间倒流、
6
+ * 地点瞬移、跨度不合理这类长篇最容易崩的地方。
7
+ */
8
+ import type { NovelApi } from '../api.ts';
9
+ export interface TimelineViewProps {
10
+ api: NovelApi;
11
+ /** 章节号列表(用于「抽取本章」下拉)。 */
12
+ chapters: number[];
13
+ }
14
+ export default function TimelineView({ api, chapters }: TimelineViewProps): JSX.Element;
@@ -0,0 +1,2 @@
1
+ /** 弹一条 toast。kind: 'done'(翡翠勾)/ 'error'(红叉)/ 'info'(中性)。 */
2
+ export declare function showToast(text: string, kind?: 'done' | 'error' | 'info'): void;
@@ -1,9 +1,15 @@
1
- /**
2
- * 纯展示组件(views):所有状态与事件处理器都留在 NovelPanel,
3
- * 这里只接收 props 渲染。便于单独维护与复用。
4
- */
5
1
  import type { ReactElement } from 'react';
6
2
  import type { AuditIssue, Plotline, PlotlineHealthReport, PlotlinePlan, RoleRecord, RoleStatusCard } from '../../protocol.ts';
3
+ /** 滑轨胶囊导航(B5-5):active 高亮为滑动指示块,随选中项平移。 */
4
+ export declare function SlideNav<T extends string>(props: {
5
+ ariaLabel: string;
6
+ items: ReadonlyArray<{
7
+ id: T;
8
+ label: ReactElement | string;
9
+ }>;
10
+ active: T;
11
+ onSelect: (id: T) => void;
12
+ }): JSX.Element;
7
13
  /** 统计格:状态摘要条 / 资产健康通用。 */
8
14
  export declare function StatCell(props: {
9
15
  label: string;
@@ -54,24 +60,36 @@ export declare function RoleCard(props: {
54
60
  onEdit: () => void;
55
61
  onRemove: () => void;
56
62
  }): ReactElement;
57
- /** 🩺 剧情健康检查报告面板。 */
63
+ /** 剧情健康检查报告面板。 */
58
64
  export declare function PlotlineHealthPanel(props: {
59
65
  report: PlotlineHealthReport;
60
66
  disabled: boolean;
61
67
  onPlan: () => void;
62
68
  onClose: () => void;
63
69
  }): ReactElement;
64
- /** ✨ AI 剧情方案面板。 */
70
+ /** 剧情方案面板。 */
65
71
  export declare function PlotlinePlanPanel(props: {
66
72
  plan: PlotlinePlan;
67
73
  disabled: boolean;
68
74
  onAdopt: (suggestion: Plotline) => void;
69
75
  onClose: () => void;
70
76
  }): ReactElement;
71
- /** ✨ AI 建议剧情线面板。 */
77
+ /** 建议剧情线面板。 */
72
78
  export declare function PlotlineSuggestionPanel(props: {
73
79
  suggestions: Plotline[];
74
80
  disabled: boolean;
75
81
  onAdopt: (suggestion: Plotline) => void;
76
82
  onClose: () => void;
77
83
  }): ReactElement;
84
+ /** 空状态基元:图标 + 标题 + 可选提示。compact 变体用于列表/卡片内嵌场景。 */
85
+ export declare function EmptyState(props: {
86
+ icon?: string;
87
+ title: string;
88
+ hint?: string;
89
+ compact?: boolean;
90
+ }): ReactElement;
91
+ /** 骨架屏基元:rows 条微光占位行;widths 指定各行宽度档位,循环取用。 */
92
+ export declare function SkeletonLines(props: {
93
+ rows?: number;
94
+ widths?: Array<'full' | 'wide' | 'half'>;
95
+ }): ReactElement;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * 运行状态芯片:固定在页面顶部的「小说工坊生成状态」小徽标。
3
+ * 轮询 /run/status,实时显示 生成中/暂停/完成/停止/出错 + 当前章号;
4
+ * 点击可打开/关闭小说工坊面板。独立 DOM 注入,不触碰主面板逻辑,挂载失败静默降级。
5
+ *
6
+ * P0 重写说明(原实现的三个问题):
7
+ * 1. 整块背景染状态色 + 固定白字 → 浅色主题下「白字配亮底」对比度崩坏。
8
+ * 现在改为「玻璃底 + 主题前景色文字 + 左侧状态色点」,状态只由色点承载,
9
+ * 文字永远跟随主题,任何深浅色下都可读。
10
+ * 2. 样式写死在 JS 的 inline style 里,切主题纹丝不动。
11
+ * 现在改用 CSS Module class,配色走 --nf-chip-* 令牌,
12
+ * 由 body[data-ds-dark-theme] 跟随宿主深浅色。
13
+ * 3. role="button" 却没有 tabindex、没有键盘处理,键盘用户完全用不了。
14
+ * 现在补 tabindex + Enter/Space 激活 + aria-label/live。
15
+ */
16
+ import type { NovelApi } from './api.ts';
17
+ import type { PanelController } from './panel/controller.ts';
18
+ /** 生成一个固定顶部的状态芯片并开始轮询。返回 dispose。 */
19
+ export declare function mountRunStatus(controller: PanelController, api: NovelApi): () => void;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * 客户端文件文本智能解码:兼容 UTF-8 BOM / UTF-16 / UTF-8 / GB18030(GBK)。
3
+ * 浏览器 File.text() 固定按 UTF-8 解码,GBK 中文网文 txt 会乱码,这里兜底。
4
+ */
5
+ /**
6
+ * 读取一个 File 的文本,按编码探测兜底解码。
7
+ * @returns 解码后的文本。
8
+ */
9
+ export declare function readFileTextSmart(file: File): Promise<string>;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * docx 文本提取共享核心:服务端(src/docx.ts)与浏览器端(src/client/docx.ts)
3
+ * 共用 XML → 纯文本的解析逻辑,避免两份实现漂移。
4
+ * zip 解压入口因运行时不同(fflate vs fflate/browser,浏览器端必须走 browser
5
+ * 入口以避开 node:module 的 require 探测)留在两端各自处理。
6
+ */
7
+ /** 解码 docx 正文实际会用到的少量 XML 实体。 */
8
+ export declare function decodeEntities(text: string): string;
9
+ /**
10
+ * 从 word/document.xml 的 XML 字符串提取纯文本:每个 <w:p> 段落一行,
11
+ * <w:tab>/<w:br> 保留为空白符;表格与嵌套结构按文档顺序拍平
12
+ * (它们的段落同样是 <w:p>)。
13
+ * @param xml - document.xml 解码后的字符串。
14
+ * @returns 正文文本(空文本时抛错)。
15
+ */
16
+ export declare function extractDocxTextFromXml(xml: string): string;
@@ -2,11 +2,10 @@
2
2
  * docx outline extraction: a .docx is a zip whose word/document.xml holds the
3
3
  * body text in <w:t> runs inside <w:p> paragraphs. We unzip with fflate and
4
4
  * walk the XML with a tiny tokenizer — no heavyweight XML/DOM dependency.
5
+ * XML 解析共享核心在 ./docx-core.ts(与浏览器端同源)。
5
6
  */
6
7
  /**
7
- * Extract plain text from a docx buffer: one line per <w:p> paragraph, with
8
- * <w:tab>/<w:br> preserved as whitespace. Tables and nested structures are
9
- * flattened in document order (their paragraphs are just <w:p> too).
8
+ * Extract plain text from a docx buffer: one line per <w:p> paragraph.
10
9
  * @param buffer - the raw .docx bytes.
11
10
  * @returns the body text.
12
11
  */