@waterwx/dsh-novel-forge 2.5.0 → 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/lib/client.js +1765 -1725
- package/lib/index.js +234 -106
- package/lib/types/assets.d.ts +2 -2
- package/lib/types/client/locales.d.ts +0 -1
- package/lib/types/client/panel/ChapterWorkbench.d.ts +69 -0
- package/lib/types/client/panel/NovelPanel.d.ts +0 -1
- package/lib/types/client/panel/WorkspaceView.d.ts +51 -0
- package/lib/types/client/panel/home-model.d.ts +53 -0
- package/lib/types/engine.d.ts +9 -1
- package/lib/types/index.d.ts +5 -1
- package/lib/types/protocol.d.ts +5 -1
- package/package.json +2 -2
package/lib/types/assets.d.ts
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Writing assets — 题材基底库 / 推进模式库 / 反 AI 规则 / 写法引擎.
|
|
3
3
|
*
|
|
4
4
|
* 内置种子数据(本项目自研表述;结构参考了同类工具的功能划分):
|
|
5
|
-
* -
|
|
6
|
-
* -
|
|
5
|
+
* - 预置叙事风格模板(数量以 {@link BUILTIN_STYLE_TEMPLATES} 数组为准)
|
|
6
|
+
* - 带命中模式的反 AI 规则(数量以 ANTI_AI_RULES 数组为准)
|
|
7
7
|
* - 题材树 + 推进模式种子
|
|
8
8
|
* Assets persist with the project (novel-project.json) and are injected into
|
|
9
9
|
* generation / planning / review prompts, and available to the AI assistant.
|
|
@@ -34,7 +34,6 @@ export declare const zh: {
|
|
|
34
34
|
readonly 'plan.pending': "待生成";
|
|
35
35
|
readonly 'plan.generating': "生成中";
|
|
36
36
|
readonly 'plan.written': "待审稿";
|
|
37
|
-
readonly 'plan.reviewing': "审稿中";
|
|
38
37
|
readonly 'plan.approved': "已通过";
|
|
39
38
|
readonly 'plan.rejected': "待修订";
|
|
40
39
|
readonly 'plan.error': "失败";
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
import type { NovelApi } from '../api.ts';
|
|
3
|
+
import type { ChapterPlan, ChapterSnapshot, Plotline, ReviewReport } from '../../protocol.ts';
|
|
4
|
+
/** 审稿维度中文名(工作台与主面板共用)。 */
|
|
5
|
+
export declare const REVIEW_DIM_ZH: Record<string, string>;
|
|
6
|
+
export declare function statusBadge(chapter: ChapterPlan): {
|
|
7
|
+
cls: string;
|
|
8
|
+
label: string;
|
|
9
|
+
};
|
|
10
|
+
/** One review issue line (severity-colored, theme-aware). */
|
|
11
|
+
export declare function severityColor(severity: string): string;
|
|
12
|
+
/** 把章节 beats 按结构标签渲染的实现见 ChapterPlanPanel.renderBeats(左栏与计划抽屉共用)。 */
|
|
13
|
+
/** The diff list of a draft-vs-original comparison (scrollable). */
|
|
14
|
+
export declare function DiffList({ original, draft, fontSize }: {
|
|
15
|
+
original: string;
|
|
16
|
+
draft: string;
|
|
17
|
+
fontSize?: number;
|
|
18
|
+
}): ReactElement;
|
|
19
|
+
/** 章节工作台右侧页签:对比(草稿 diff)/ 审稿(AI 审稿报告)/ 复盘(作者复盘)。 */
|
|
20
|
+
export type ChapterSideTab = 'diff' | 'review' | 'author' | 'versions';
|
|
21
|
+
/** 章节工作台(独立全页)需要的全部输入;所有数据来自真实 project.chapters。 */
|
|
22
|
+
interface ChapterWorkbenchProps {
|
|
23
|
+
chapter: ChapterPlan;
|
|
24
|
+
bookKey: string;
|
|
25
|
+
/** 已加载的正文 markdown;'' 表示未加载 / 尚未生成。 */
|
|
26
|
+
text: string;
|
|
27
|
+
/** 润色 / 修订草稿;存在时「对比」页可做逐段 diff。 */
|
|
28
|
+
draft?: string;
|
|
29
|
+
fontSize: number;
|
|
30
|
+
busy: boolean;
|
|
31
|
+
busyAny: boolean;
|
|
32
|
+
onBack: () => void;
|
|
33
|
+
onWrite: () => void;
|
|
34
|
+
onReview: () => void;
|
|
35
|
+
onApprove: () => void;
|
|
36
|
+
onEdit: () => void;
|
|
37
|
+
/** 按作者勾选的审稿意见修订(不传则内部自动挑 high)。 */
|
|
38
|
+
onRevisePicked: (issues: ReviewReport['issues']) => void;
|
|
39
|
+
onReset: () => void;
|
|
40
|
+
onRegenerate: () => void;
|
|
41
|
+
onBackfillAuthor: () => void;
|
|
42
|
+
/** 右栏当前页签(受控:修订完成后由外层自动切到「对比」)。 */
|
|
43
|
+
tab: ChapterSideTab;
|
|
44
|
+
onTabChange: (tab: ChapterSideTab) => void;
|
|
45
|
+
/** 草稿审查报告(验证模式产物,针对草稿本身);null = 还没审查过。 */
|
|
46
|
+
draftReport: ReviewReport | null;
|
|
47
|
+
onApplyDraft: () => void;
|
|
48
|
+
onDiscardDraft: () => void;
|
|
49
|
+
onCheckDraft: () => void;
|
|
50
|
+
/** 本章历史版本(快照)与回滚/存档动作。 */
|
|
51
|
+
snapshots: ChapterSnapshot[];
|
|
52
|
+
onRestoreSnapshot: (id: string) => void;
|
|
53
|
+
onCreateSnapshot: () => void;
|
|
54
|
+
/** 左栏「本章计划」:剧情线用于关联项,api + onPlanSaved 提供就地补写通道。 */
|
|
55
|
+
plotlines: Plotline[];
|
|
56
|
+
api: NovelApi;
|
|
57
|
+
onPlanSaved: (chapter: ChapterPlan) => void;
|
|
58
|
+
/** 截断声明汇入外层进度台。 */
|
|
59
|
+
onNotice: (message: string) => void;
|
|
60
|
+
onLinkLines: () => void;
|
|
61
|
+
/** 失败态的出路之一:打开「AI 进度」浮窗看这一章的运行详情(Prompt / 耗时 / 原始错误)。 */
|
|
62
|
+
onOpenRunLog: () => void;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* 章节工作台:**独立全页**(不塞进抽屉或主从布局,内容太重)。
|
|
66
|
+
* 三栏并发 —— 左:本章计划(六项固定分组,见 ChapterPlanPanel);中:正文;右:对比 / 审稿 / 复盘 / 历史。
|
|
67
|
+
*/
|
|
68
|
+
export declare function ChapterWorkbench({ chapter, bookKey, text, draft, fontSize, busy, busyAny, onBack, onWrite, onReview, onApprove, onEdit, onRevisePicked, onReset, onRegenerate, onBackfillAuthor, tab, onTabChange, draftReport, onApplyDraft, onDiscardDraft, onCheckDraft, snapshots, onRestoreSnapshot, onCreateSnapshot, plotlines, api, onPlanSaved, onNotice, onLinkLines, onOpenRunLog, }: ChapterWorkbenchProps): ReactElement;
|
|
69
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 润色 / 修订工作区(全页受控组件)。
|
|
3
|
+
*
|
|
4
|
+
* 从 NovelPanel.tsx 抽出(2026-10 重构第二步):它是一整页编辑器,原先直接嵌在
|
|
5
|
+
* 5600 行主组件的 return 里,任何一处改动都要翻过上百行 JSX。这里只做**受控渲染**:
|
|
6
|
+
* 状态与请求逻辑仍留在面板(它要驱动全局 busy / 进度台 / 刷新),视图只负责把
|
|
7
|
+
* props 接上——纯搬家,不搬行为。
|
|
8
|
+
*/
|
|
9
|
+
import type { Dispatch, MutableRefObject, SetStateAction } from 'react';
|
|
10
|
+
import type { ReactElement } from 'react';
|
|
11
|
+
import type { ReviewReport } from '../../protocol.ts';
|
|
12
|
+
/** 工作区状态(面板持有)。 */
|
|
13
|
+
export interface WorkspaceState {
|
|
14
|
+
no: number;
|
|
15
|
+
title: string;
|
|
16
|
+
original: string;
|
|
17
|
+
instruction: string;
|
|
18
|
+
draft: string | null;
|
|
19
|
+
/** 打开工作区时的正文基线(用于判断"有未保存修改")。 */
|
|
20
|
+
baseline: string;
|
|
21
|
+
/** 已采纳草稿(原地结论态):显示已采纳横幅 + 自动审稿结果,返回时才关闭工作区。 */
|
|
22
|
+
applied?: boolean;
|
|
23
|
+
}
|
|
24
|
+
/** 工作区视图的全部输入;状态与副作用都由面板提供。 */
|
|
25
|
+
export interface WorkspaceViewProps {
|
|
26
|
+
workspace: WorkspaceState;
|
|
27
|
+
onWorkspaceChange: (next: WorkspaceState) => void;
|
|
28
|
+
onClose: () => void;
|
|
29
|
+
onGotoChapter: (no: number) => void;
|
|
30
|
+
backTo: string;
|
|
31
|
+
editorFontSize: number;
|
|
32
|
+
onEditorFontSizeChange: (n: number) => void;
|
|
33
|
+
editorRef: MutableRefObject<HTMLTextAreaElement | null>;
|
|
34
|
+
selected: string;
|
|
35
|
+
onCaptureSelection: () => void;
|
|
36
|
+
checkReport: ReviewReport | null;
|
|
37
|
+
checked: number[];
|
|
38
|
+
onCheckedChange: Dispatch<SetStateAction<number[]>>;
|
|
39
|
+
showDiff: boolean;
|
|
40
|
+
onShowDiffChange: (next: boolean) => void;
|
|
41
|
+
resultMode: boolean;
|
|
42
|
+
busy: boolean;
|
|
43
|
+
onReviseByReport: () => void;
|
|
44
|
+
onRewrite: (whole: boolean) => void;
|
|
45
|
+
onPolish: () => void;
|
|
46
|
+
onSave: () => void;
|
|
47
|
+
onCheck: () => void;
|
|
48
|
+
onDiscardDraft: (no: number) => void;
|
|
49
|
+
}
|
|
50
|
+
/** 工作区全页:左栏原文(可选中局部目标)+ 右栏指令 / 预览 / 应用。 */
|
|
51
|
+
export declare function WorkspaceView({ workspace, onWorkspaceChange, onClose, onGotoChapter, backTo, editorFontSize, onEditorFontSizeChange, editorRef, selected, onCaptureSelection, checkReport, checked, onCheckedChange, showDiff, onShowDiffChange, resultMode, busy, onReviseByReport, onRewrite, onPolish, onSave, onCheck, onDiscardDraft, }: WorkspaceViewProps): ReactElement;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 总编台(首页)的纯计算层。
|
|
3
|
+
*
|
|
4
|
+
* 从 NovelPanel.tsx 抽出(2026-10 重构):这些数字原先散在 6000+ 行组件的
|
|
5
|
+
* useMemo 里,既没法单测,也让「同一件事在面板里说两遍」难以发现。抽成纯函数后:
|
|
6
|
+
* - 输入只有 project / chapters,输出是确定的结构;
|
|
7
|
+
* - 面板只负责渲染,数字口径集中在这里改;
|
|
8
|
+
* - `tests/home-model.test.ts` 直接覆盖边界(空书、全过审、生成中)。
|
|
9
|
+
*/
|
|
10
|
+
import type { ChapterPlan, ProjectState } from '../../protocol.ts';
|
|
11
|
+
/** 总编台用的章节统计(一次遍历算完,避免面板里重复过滤)。 */
|
|
12
|
+
export interface ChapterStats {
|
|
13
|
+
/** 有正文的章数(approved / written / rejected)。 */
|
|
14
|
+
done: number;
|
|
15
|
+
/** 待处理章数(pending / error)。 */
|
|
16
|
+
pending: number;
|
|
17
|
+
/** 已过审章数。 */
|
|
18
|
+
approved: number;
|
|
19
|
+
/** 待审章数(written / rejected)。 */
|
|
20
|
+
reviewPending: number;
|
|
21
|
+
/** 全书已写字数(汉字口径,来自 chapter.chars)。 */
|
|
22
|
+
totalChars: number;
|
|
23
|
+
/** 正在生成的章(同刻至多一章;undefined = 没有)。 */
|
|
24
|
+
writingNow: ChapterPlan | undefined;
|
|
25
|
+
/** 逐章字数序列(Sparkline 用;顺序 = 章节数组顺序)。 */
|
|
26
|
+
charSeries: Array<{
|
|
27
|
+
no: number;
|
|
28
|
+
chars: number;
|
|
29
|
+
approved: boolean;
|
|
30
|
+
}>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 单次遍历统计全书章节。
|
|
34
|
+
* @param chapters 全书章节计划(顺序无关,按数组顺序输出 charSeries)。
|
|
35
|
+
*/
|
|
36
|
+
export declare function computeChapterStats(chapters: ChapterPlan[]): ChapterStats;
|
|
37
|
+
/** 创作旅程的一个阶段。 */
|
|
38
|
+
export interface JourneyStage {
|
|
39
|
+
id: string;
|
|
40
|
+
label: string;
|
|
41
|
+
done: boolean;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 创作旅程 6 阶段(大纲 → 设定 → 卷计划 → 章节计划 → 正文 → 审稿)。
|
|
45
|
+
*
|
|
46
|
+
* 「完成」的判定只看项目真实数据,不参考 UI 当前所在页;否则作者在
|
|
47
|
+
* 「总纲」页多停留一会儿,旅程条就会自己变。
|
|
48
|
+
*
|
|
49
|
+
* @param project 当前书(undefined = 没有书)。
|
|
50
|
+
* @param chapters 章节计划。
|
|
51
|
+
* @param approvedCount 已过审章数(来自 {@link computeChapterStats})。
|
|
52
|
+
*/
|
|
53
|
+
export declare function computeJourneyStages(project: ProjectState | undefined, chapters: ChapterPlan[], approvedCount: number): JourneyStage[];
|
package/lib/types/engine.d.ts
CHANGED
|
@@ -502,11 +502,18 @@ export declare function extractTimelineForChapter(ctx: Context, config: NovelCon
|
|
|
502
502
|
* @returns 模型给出的问题清单(与规则初筛结果合并由调用方决定)。
|
|
503
503
|
*/
|
|
504
504
|
export declare function reviewTimeline(ctx: Context, config: NovelConfig, project: ProjectState): Promise<TimelineIssue[]>;
|
|
505
|
-
/**
|
|
505
|
+
/**
|
|
506
|
+
* Export the whole book as one txt/md file.
|
|
507
|
+
*
|
|
508
|
+
* 只收真实存在且非空的章节文件:`chapter.file` 有值不等于文件没被手删/清空,
|
|
509
|
+
* 旧实现会把它们当空串拼进去,导出件看起来完整、实际缺章。跳过的章号随
|
|
510
|
+
* `skipped` 一起返回,由面板如实提示。
|
|
511
|
+
*/
|
|
506
512
|
export declare function exportBook(outputDir: string, project: ProjectState, format: 'txt' | 'md'): {
|
|
507
513
|
file: string;
|
|
508
514
|
chars: number;
|
|
509
515
|
chapters: number;
|
|
516
|
+
skipped?: number[];
|
|
510
517
|
};
|
|
511
518
|
/**
|
|
512
519
|
* 按范围导出:整本正文 / 设定 / 规划 / 角色 / 质检记录 / 项目 JSON。
|
|
@@ -521,4 +528,5 @@ export declare function exportScope(outputDir: string, project: ProjectState, sc
|
|
|
521
528
|
file: string;
|
|
522
529
|
chars: number;
|
|
523
530
|
chapters: number;
|
|
531
|
+
skipped?: number[];
|
|
524
532
|
};
|
package/lib/types/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import type { Context } from '@deepseek-ai/cordis';
|
|
10
10
|
import z from 'schemastery';
|
|
11
|
-
import type { NovelConfig } from './protocol.ts';
|
|
11
|
+
import type { NovelConfig, SavedModel } from './protocol.ts';
|
|
12
12
|
/** Stable cordis plugin name. */
|
|
13
13
|
export declare const name = "novel-forge";
|
|
14
14
|
/** Services required before the novel-forge surfaces can mount. */
|
|
@@ -47,6 +47,8 @@ export interface Config {
|
|
|
47
47
|
auditModel?: string;
|
|
48
48
|
/** 备用模型:主模型失败时自动切换重试一次(留空 = 不切换)。 */
|
|
49
49
|
fallbackModel?: string;
|
|
50
|
+
/** 备用模型的输出 token 上限(仅在设了 fallbackModel 时有意义;0/空 = 沿用主模型预算)。 */
|
|
51
|
+
fallbackMaxTokens?: number;
|
|
50
52
|
/** 出章后自动抽取故事时间线(默认开)。 */
|
|
51
53
|
autoTimeline?: boolean;
|
|
52
54
|
/** LLM reasoning effort (off/low/high/max). */
|
|
@@ -73,6 +75,8 @@ export interface Config {
|
|
|
73
75
|
themeOpacity?: number;
|
|
74
76
|
/** 是否启用改编模式(默认关闭)。 */
|
|
75
77
|
enableAdaptMode?: boolean;
|
|
78
|
+
/** 手动添加的模型库(「我的模型」条目;只存插件内)。 */
|
|
79
|
+
savedModels?: SavedModel[];
|
|
76
80
|
}
|
|
77
81
|
/**
|
|
78
82
|
* Plugin config schema.
|
package/lib/types/protocol.d.ts
CHANGED
|
@@ -265,7 +265,7 @@ export interface BookImportTextPreviewResponse {
|
|
|
265
265
|
skipped: string[];
|
|
266
266
|
}
|
|
267
267
|
/** Chapter lifecycle states (the writing pipeline's state machine). */
|
|
268
|
-
export type ChapterStatus = 'pending' | 'generating' | 'written' | '
|
|
268
|
+
export type ChapterStatus = 'pending' | 'generating' | 'written' | 'approved' | 'rejected' | 'error';
|
|
269
269
|
/** One chapter in the plan. */
|
|
270
270
|
export interface ChapterPlan {
|
|
271
271
|
/** 1-based chapter number (stable identity; files are named from it). */
|
|
@@ -1868,6 +1868,8 @@ export interface ExportResponse {
|
|
|
1868
1868
|
file: string;
|
|
1869
1869
|
chars: number;
|
|
1870
1870
|
chapters: number;
|
|
1871
|
+
/** 全本导出时因文件缺失/为空被跳过的章号;无跳过项时缺省。 */
|
|
1872
|
+
skipped?: number[];
|
|
1871
1873
|
scope: ExportScope;
|
|
1872
1874
|
format: 'txt' | 'md' | 'json';
|
|
1873
1875
|
}
|
|
@@ -1882,6 +1884,8 @@ export interface ConfigPatch {
|
|
|
1882
1884
|
auditModel?: string;
|
|
1883
1885
|
/** 备用模型(主模型失败时自动切换重试一次;空串 = 关闭)。 */
|
|
1884
1886
|
fallbackModel?: string;
|
|
1887
|
+
/** 备用模型的输出 token 上限(0/空 = 沿用主模型预算)。 */
|
|
1888
|
+
fallbackMaxTokens?: number;
|
|
1885
1889
|
/** 出章后自动抽取故事时间线(默认开)。 */
|
|
1886
1890
|
autoTimeline?: boolean;
|
|
1887
1891
|
reasoningEffort?: 'off' | 'low' | 'high' | 'max';
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@waterwx/dsh-novel-forge",
|
|
3
3
|
"description": "AI 编译纯文本小说工作台 for the dsh web GUI: import a novel outline (docx/text), plan volumes & chapters with LLM, generate chapter by chapter (3000-4000 chars each), auto AI review & book audit, and export the full book as Markdown/TXT into your chosen output folder.",
|
|
4
|
-
"version": "2.5.
|
|
4
|
+
"version": "2.5.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "waterwx",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
|
-
"url": "https://github.com/watersxya/dsh-novel-forge.git"
|
|
9
|
+
"url": "git+https://github.com/watersxya/dsh-novel-forge.git"
|
|
10
10
|
},
|
|
11
11
|
"homepage": "https://github.com/watersxya/dsh-novel-forge",
|
|
12
12
|
"bugs": {
|