@waterwx/dsh-novel-forge 1.3.0-alpha → 1.3.1-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,9 @@
1
1
  /**
2
- * Tiny translation helper for the panel: reads the zh dict with the en dict
3
- * as fallback (the family plugins use a full locale registry; the panel keeps
4
- * a dependency-free helper so the client bundle stays self-contained).
2
+ * Tiny translation helper for the panel.
3
+ *
4
+ * 面板是中文单语界面:文案只在 `locales.ts` 定义一次,这里按类型化键位取值
5
+ * (键位不匹配会在编译期报错),保持客户端 bundle 自包含、不引入运行时语言服务。
6
+ * 需要多语言时再接入 DSH 的 locale 服务,届时只需替换本函数实现。
5
7
  */
6
8
  import { type NovelKey } from '../locales.ts';
7
9
  /** Translate one key with optional {placeholder} substitution. */
@@ -70,7 +70,7 @@ export interface Config {
70
70
  }
71
71
  export declare const Config: z<Config>;
72
72
  /** Model-facing announcement: plugin presence, capabilities, and limits. */
73
- export declare const NOVEL_GUIDANCE = "\u672C\u673A\u5DF2\u5B89\u88C5 dsh-novel-forge \u63D2\u4EF6\uFF08AI \u7F16\u8BD1\u5C0F\u8BF4\u5DE5\u4F5C\u53F0\uFF09\uFF1A\u4FA7\u8FB9\u680F\u300C\u5C0F\u8BF4\u5DE5\u574A\u300D\u5165\u53E3\u3002\u80FD\u529B\uFF1A\u8BFB\u53D6 docx \u5927\u7EB2\u6216\u7C98\u8D34\u5927\u7EB2\u6587\u672C\uFF1B\u7528 LLM \u63D0\u70BC\u9053\u85CF\uFF08\u4EBA\u8BBE/\u4E16\u754C\u89C2/\u91D1\u624B\u6307\u89C4\u5219/\u5199\u4F5C\u7EA2\u7EBF\uFF09\uFF1B\u751F\u6210\u5377\u8BA1\u5212\u4E0E\u7AE0\u8282\u8BA1\u5212\uFF1B\u9010\u7AE0\u8C03\u7528 LLM \u751F\u6210 3000-4000 \u5B57\u6B63\u6587\u5E76\u4FDD\u5B58\u4E3A Markdown\uFF08\u9ED8\u8BA4\u8F93\u51FA\u5230\u7528\u6237\u4E3B\u76EE\u5F55 ~/.dsh/novels\uFF09\uFF1B\u6BCF\u7AE0\u81EA\u52A8\u751F\u6210\u6458\u8981\uFF08\u53D9\u4E8B\u8BB0\u5FC6\uFF09\u3001\u81EA\u52A8 AI \u5BA1\u7A3F\uFF08\u4EBA\u8BBE/\u8BBE\u5B9A/\u7EA2\u7EBF/\u6587\u7B14/\u723D\u70B9/\u903B\u8F91\uFF09\uFF0C\u652F\u6301\u6309\u5BA1\u7A3F\u610F\u89C1\u91CD\u5199\u3001\u53BB AI \u5473\u6DA6\u8272\u3001\u6697\u7EBF\uFF08\u4F0F\u7B14\uFF09\u7BA1\u7406\u3001\u6279\u91CF\u8FDE\u5199\u4E0E\u5168\u672C\u5BFC\u51FA\uFF08txt/md\uFF09\u3002\u9650\u5236\uFF1A\u751F\u6210\u6D88\u8017 LLM API \u989D\u5EA6\uFF1B\u8F93\u51FA\u76EE\u5F55\u4E0E\u6A21\u578B\u53EF\u5728\u63D2\u4EF6\u8BBE\u7F6E\u4E2D\u4FEE\u6539\uFF1B\u7AE0\u8282\u6B63\u6587\u8D28\u91CF\u53D6\u51B3\u4E8E\u5927\u7EB2\u5B8C\u6574\u5EA6\u3002\u7528\u6237\u63D0\u5230\u300C\u5C0F\u8BF4 / \u5927\u7EB2 / \u5199\u5C0F\u8BF4 / \u7AE0\u8282 / \u5BA1\u7A3F / \u6DA6\u8272\u300D\u65F6\u5373\u6307\u672C\u63D2\u4EF6\uFF0C\u8BF7\u636E\u6B64\u534F\u4F5C\u3002";
73
+ export declare const NOVEL_GUIDANCE = "\u672C\u673A\u5DF2\u5B89\u88C5 dsh-novel-forge \u63D2\u4EF6\uFF08AI \u7F16\u8BD1\u5C0F\u8BF4\u5DE5\u4F5C\u53F0\uFF09\uFF1A\u4FA7\u8FB9\u680F\u300C\u5C0F\u8BF4\u5DE5\u574A\u300D\u5165\u53E3\u3002\u80FD\u529B\uFF1A\u8BFB\u53D6 docx \u5927\u7EB2\u3001\u7C98\u8D34\u5927\u7EB2\u6587\u672C\u6216\u628A txt \u5168\u672C\u62C6\u7AE0\u5BFC\u5165\uFF1B\u7528 LLM \u63D0\u70BC\u9053\u85CF\uFF08\u4EBA\u8BBE/\u4E16\u754C\u89C2/\u91D1\u624B\u6307\u89C4\u5219/\u5199\u4F5C\u7EA2\u7EBF\uFF09\u4E0E\u5927\u4E16\u754C\uFF08\u5883\u754C/\u533A\u57DF/\u52BF\u529B\uFF09\uFF1B\u751F\u6210\u5377\u8BA1\u5212\u4E0E\u7ED3\u6784\u5316\u7AE0\u8282\u8BA1\u5212\uFF08\u672C\u7AE0\u76EE\u6807/\u5267\u60C5\u8981\u70B9/\u5FC5\u8FBE\u9879/\u4E49\u52A1\u5408\u7EA6/\u7AE0\u672B\u94A9\u5B50\uFF09\uFF1B\u9010\u7AE0\u751F\u6210 3000-4000 \u5B57\u6B63\u6587\u5E76\u4FDD\u5B58\u4E3A Markdown\uFF08\u9ED8\u8BA4\u8F93\u51FA\u5230\u7528\u6237\u4E3B\u76EE\u5F55 ~/.dsh/novels\uFF09\uFF1B\u6BCF\u7AE0\u81EA\u52A8\u751F\u6210\u6458\u8981\u4E0E\u7F16\u5E74\u5F55\u4E8B\u5B9E\u3001\u62BD\u53D6\u6545\u4E8B\u65F6\u95F4\u7EBF\uFF08\u6545\u4E8B\u5185\u65F6\u95F4/\u5730\u70B9/\u5728\u573A\u89D2\u8272/\u4E8B\u4EF6\uFF09\u3001\u81EA\u52A8 AI \u5BA1\u7A3F\uFF08\u4EBA\u8BBE/\u8BBE\u5B9A/\u7EA2\u7EBF/\u6587\u7B14/\u723D\u70B9/\u903B\u8F91/\u53CD AI/\u5448\u73B0/\u5408\u89C4\u4E5D\u7EF4\uFF09\u4E0E\u4F5C\u8005\u590D\u76D8\uFF1B\u652F\u6301\u6309\u5BA1\u7A3F\u610F\u89C1\u5408\u5E76\u4FEE\u8BA2\uFF08\u5BA1\u7A3F high + \u65F6\u95F4\u7EBF\u77DB\u76FE + \u5F20\u529B\u504F\u5DEE\u5408\u6210\u4E00\u8F6E\uFF0C\u6BCF\u7AE0\u6700\u591A\u4E24\u8F6E\u540E\u8F6C\u4EBA\u5DE5\uFF09\u3001\u53BB AI \u5473\u6DA6\u8272\u3001\u7AE0\u8282\u5386\u53F2\u7248\u672C\u56DE\u6EDA\u3001\u6697\u7EBF\uFF08\u4F0F\u7B14\uFF09\u7BA1\u7406\u3001\u5267\u60C5\u7EBF\u4E0E\u89D2\u8272\u5E93\u3001\u5F20\u529B\u66F2\u7EBF\u3001\u5168\u4E66\u4E00\u81F4\u6027\u8D28\u68C0\u4E0E\u654F\u611F\u8BCD\u626B\u63CF\u3001\u5206\u8303\u56F4\u5BFC\u51FA\u4E0E\u9879\u76EE\u5907\u4EFD\u3001\u6279\u91CF\u8FDE\u5199\uFF08\u751F\u4EA7\u5355\uFF0C\u53EF\u6682\u505C/\u7EED\u8DD1\uFF09\u3002\u9650\u5236\uFF1A\u6240\u6709 AI \u64CD\u4F5C\u6D88\u8017 LLM API \u989D\u5EA6\uFF1B\u8F93\u51FA\u76EE\u5F55\u4E0E\u6A21\u578B\u53EF\u5728\u63D2\u4EF6\u8BBE\u7F6E\u4E2D\u4FEE\u6539\uFF1B\u7AE0\u8282\u6B63\u6587\u8D28\u91CF\u53D6\u51B3\u4E8E\u5927\u7EB2\u5B8C\u6574\u5EA6\uFF1B\u5F20\u529B/\u65F6\u95F4\u7EBF\u95EE\u9898\u9ED8\u8BA4\u53EA\u662F\u5EFA\u8BAE\uFF08\u5199\u65E5\u5FD7\u4E0E\u5F85\u529E\uFF09\uFF0C\u4E0D\u4F1A\u81EA\u52A8\u6539\u6B63\u6587\u3002\u7528\u6237\u63D0\u5230\u300C\u5C0F\u8BF4 / \u5927\u7EB2 / \u5199\u5C0F\u8BF4 / \u7AE0\u8282 / \u5BA1\u7A3F / \u6DA6\u8272\u300D\u65F6\u5373\u6307\u672C\u63D2\u4EF6\uFF0C\u8BF7\u636E\u6B64\u534F\u4F5C\u3002";
74
74
  /** Resolve a config-like value into the full runtime config. */
75
75
  export declare function resolveConfig(value: Partial<Config> | undefined): NovelConfig;
76
76
  /**
@@ -29,6 +29,8 @@ export declare const NOVEL_API: {
29
29
  readonly usageReset: "/api/dsh-novel-forge/usage/reset";
30
30
  /** 章节历史版本(快照)。 */
31
31
  readonly snapshot: "/api/dsh-novel-forge/snapshot";
32
+ /** 修订指令合并(POST:汇总审稿/时间线/张力为一轮)。 */
33
+ readonly revisionPlan: "/api/dsh-novel-forge/revision/plan";
32
34
  /** 张力曲线(GET 数据 / POST 设置)。 */
33
35
  readonly tension: "/api/dsh-novel-forge/tension";
34
36
  /** 提示词槽位(GET 列表 / POST 写入)。 */
@@ -341,9 +343,11 @@ export interface AuthorReview {
341
343
  /** 审稿维度(结构化定位问题类别;与 review-policy.ts 的 REVIEW_DIMENSIONS 对齐)。 */
342
344
  export type ReviewDimension = 'character' | 'setting' | 'redline' | 'writing' | 'pacing' | 'logic' | 'anti-ai' | 'presentation' | 'compliance';
343
345
  /** One review finding. */
346
+ /** 问题严重度(审稿 / 时间线 / 张力共用)。 */
347
+ export type Severity = 'high' | 'medium' | 'low';
344
348
  export interface ReviewIssue {
345
349
  /** Severity: high = must fix, medium = should fix, low = suggestion. */
346
- severity: 'high' | 'medium' | 'low';
350
+ severity: Severity;
347
351
  /** 问题维度(可选;缺省由前端按 item 推断)。 */
348
352
  dimension?: ReviewDimension;
349
353
  /** What the problem is. */
@@ -578,6 +582,45 @@ export interface StoryBible {
578
582
  generatedAt?: string;
579
583
  }
580
584
  /** A planted/active/resolved foreshadowing thread. */
585
+ /** 修订建议来源:审稿 / 时间线 / 张力。 */
586
+ export type RevisionSource = 'review' | 'timeline' | 'tension';
587
+ /** 一条待修订条目(合并层排序后的最小单位)。 */
588
+ export interface RevisionItem {
589
+ /** 稳定 id(source:chapter:index)。 */
590
+ id: string;
591
+ source: RevisionSource;
592
+ severity: Severity;
593
+ /** 归属章节号(0 = 全书级)。 */
594
+ chapterNo: number;
595
+ item: string;
596
+ suggestion: string;
597
+ /** 去重时合并掉的同类条数(>=2 时展示)。 */
598
+ count?: number;
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
+ /** POST /revision/plan 响应。 */
611
+ export interface RevisionPlanResponse {
612
+ chapterNo: number;
613
+ items: RevisionItem[];
614
+ /** 唯一修订指令(面板直接把它交给 /rewrite)。 */
615
+ instruction: string;
616
+ counts: Record<RevisionSource, number>;
617
+ /** 因上限被截断的条数。 */
618
+ omitted: number;
619
+ /** 验证基准(复核时逐条核对本轮下发的全部条目)。 */
620
+ baseline: ReviewReport;
621
+ /** 一行摘要。 */
622
+ summary: string;
623
+ }
581
624
  /**
582
625
  * 张力曲线形状预设:
583
626
  * `escalation` 递进爬升 / `suspense` 悬疑加压 / `wave` 波浪呼吸 /
@@ -0,0 +1,76 @@
1
+ /**
2
+ * 修订指令合并层(arbitration)。
3
+ *
4
+ * 问题:审稿、时间线、张力三条通道各自给建议,如果各自改一轮,会出现「改完 A 又违反 B」
5
+ * 的互相打脸:同一章可能被改三遍,最后一轮的改动把第一轮的修正覆盖掉。
6
+ *
7
+ * 规则(与面板/生产单共享同一份实现,避免两头各写一套):
8
+ * 1. 同一章只交付**一份**修订指令(本模块负责汇总,调用方不得自行拼装)。
9
+ * 2. 固定优先级,不做权重打分(可解释、可复现):
10
+ * 0 审稿 high(必改,是硬门)
11
+ * 1 时间线 high(硬矛盾:时间倒流、地点瞬移)
12
+ * 2 张力 medium(曲线偏差,建议性最强)
13
+ * 3 其余(审稿 medium / 时间线 medium)
14
+ * 4 低优先(审稿 low)
15
+ * 3. 一次修订最多吃 REVISION_ITEM_CAP 条,超出按优先级截断;截断数量显式回传,不静默丢弃。
16
+ * 4. 每章修订轮次上限 MAX_REVISION_ROUNDS,超出转人工待办。
17
+ * 5. 验证基准 = 本轮实际下发的全部条目(审稿 + 时间线 + 张力),
18
+ * 这样「复核」核对的就是「我们要求改的东西」,而不是只核对审稿那部分。
19
+ */
20
+ import type { ProjectState, ReviewIssue, ReviewReport, RevisionItem, RevisionSource, Severity } from './protocol.js';
21
+ /** 每章修订轮次上限:两轮仍不过即转人工,不做「无限自动修改」。 */
22
+ export declare const MAX_REVISION_ROUNDS = 2;
23
+ /** 单次修订指令最多携带的条目数(防止指令过长把正文挤出上下文)。 */
24
+ export declare const REVISION_ITEM_CAP = 8;
25
+ export declare const REVISION_SOURCE_LABELS: Record<RevisionSource, string>;
26
+ /** 固定优先级:数值越小越先改。 */
27
+ export declare function revisionPriority(source: RevisionSource, severity: Severity): number;
28
+ /** 排序 + 去重 + 截断。去重时保留优先级更高的那条,并累加 count。 */
29
+ export declare function mergeRevisionItems(items: RevisionItem[], cap?: number): {
30
+ items: RevisionItem[];
31
+ omitted: number;
32
+ };
33
+ export interface RevisionCollectOptions {
34
+ /** 目标章;缺省表示全书(用于整本批量修订)。 */
35
+ chapterNo?: number;
36
+ /** 显式指定的审稿意见;缺省取该章已落盘的审稿报告。 */
37
+ reviewIssues?: ReviewIssue[];
38
+ /** 是否纳入时间线矛盾(默认纳入)。 */
39
+ includeTimeline?: boolean;
40
+ /** 是否纳入张力偏差(默认纳入)。 */
41
+ includeTension?: boolean;
42
+ }
43
+ /** 汇总一章(或全书)的三类建议。纯函数,不改项目状态。 */
44
+ export declare function collectRevisionItems(project: ProjectState, options?: RevisionCollectOptions): RevisionItem[];
45
+ export interface RevisionPlan {
46
+ /** 已排序、去重、截断后的条目。 */
47
+ items: RevisionItem[];
48
+ /** 下发给模型的修订指令(唯一入口,调用方不要自行拼装)。 */
49
+ instruction: string;
50
+ counts: Record<RevisionSource, number>;
51
+ /** 因超出上限被截断的条数(显式回传,便于提示作者)。 */
52
+ omitted: number;
53
+ /** 验证基准:把本轮下发的全部条目当作「上一轮意见」,复核时逐条核对。 */
54
+ baseline: ReviewReport;
55
+ }
56
+ export interface BuildRevisionPlanOptions extends RevisionCollectOptions {
57
+ /** 审稿基线报告(提供后 baseline 会保留其分数与时间)。 */
58
+ baseReport?: ReviewReport;
59
+ /** 指令抬头(默认「按合并建议修订」)。 */
60
+ title?: string;
61
+ cap?: number;
62
+ }
63
+ /** 渲染修订指令。格式与历史「按审稿意见修订」保持同族,模型无需重新学习。 */
64
+ export declare function renderRevisionInstruction(items: RevisionItem[], title?: string): string;
65
+ /**
66
+ * 构造验证基准:把时间线/张力条目转成「上一轮意见」的编号项,
67
+ * 与审稿意见合并成一份报告。复核模型据此逐条核对,避免
68
+ * 「审稿说已解决、时间线说没改」这类互相打架的判定。
69
+ */
70
+ export declare function buildRevisionBaseline(items: RevisionItem[], base?: ReviewReport): ReviewReport;
71
+ /** 汇总 → 排序 → 指令 → 基准。面板与生产单都走这里。 */
72
+ export declare function buildRevisionPlan(project: ProjectState, options?: BuildRevisionPlanOptions): RevisionPlan;
73
+ /** 一行摘要,用于日志与面板提示("审稿 3 · 时间线 1 · 张力 1,另截断 2 条")。 */
74
+ export declare function describeRevisionPlan(plan: RevisionPlan): string;
75
+ /** 待办文本(生产单只提示不阻塞时写入项目待办,供作者人工决定)。 */
76
+ export declare function revisionTodoText(item: RevisionItem): string;
@@ -26,6 +26,14 @@ export declare class ProductionRunner {
26
26
  /** 主循环:从 currentNo 扫描到 endNo,逐章处理;支持暂停/停止。 */
27
27
  private loop;
28
28
  private processChapter;
29
+ /**
30
+ * 出章即核对曲线(建议性,不阻塞):
31
+ * 规则初筛得到的时间线矛盾 + 张力曲线偏差写进运行日志;本章已完结时再落成项目待办。
32
+ * 默认**不**触发任何自动修订——要看/要改由作者在面板发起「一键按建议修订」;
33
+ * 只有当本章因审稿 high 本来就要修订时,这些问题才搭同一轮车(见 handleRejected),
34
+ * 因此不额外增加轮次,也不会出现「改完甲又违反乙」。
35
+ */
36
+ private auditChapterAdvisories;
29
37
  /** 完整质量门:生成 → 摘要+事实 → 伏笔标记 → 审稿 → 作者复盘。 */
30
38
  private produce;
31
39
  /** 被拒分级处理:无 high 豁免;有 high 按意见修订(最多 2 轮)+ 验证模式;仍不过 → 待人工。 */
@@ -34,18 +34,6 @@ export declare function clampTension(value: number): number;
34
34
  * @returns 提示词片段;没有张力信息时返回空串。
35
35
  */
36
36
  export declare function renderTensionBlock(project: ProjectState, chapterNo: number): string;
37
- /**
38
- * 规则核对张力曲线(不调模型)。
39
- *
40
- * 检查四类曲线级问题:
41
- * 1) 实际与目标偏差过大(>25);
42
- * 2) 连续多章几乎同值(≥4 章落差 <6,平台期无起伏);
43
- * 3) 高点之后没有回落(连续 ≥3 章处在高位 ≥80);
44
- * 4) 长期低位(连续 ≥5 章 <40,容易拖沓)。
45
- *
46
- * @param project 项目状态。
47
- * @returns 问题清单(可能为空)。
48
- */
49
37
  export declare function detectTensionIssues(project: ProjectState): TensionIssue[];
50
38
  /**
51
39
  * 组装面板需要的曲线数据(章节号 / 目标 / 实际 / 参考)。
package/package.json CHANGED
@@ -1,7 +1,7 @@
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": "1.3.0-alpha",
4
+ "version": "1.3.1-alpha",
5
5
  "type": "module",
6
6
  "author": "waterwx",
7
7
  "repository": {