@cloud411716/fancy-webnovel 1.0.46 → 2.2.0

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 (134) hide show
  1. package/client.js +183 -0
  2. package/cordis.patch.yml +0 -14
  3. package/index.js +21 -37
  4. package/lib/chinese-num.js +111 -0
  5. package/lib/deployed-state.js +141 -0
  6. package/lib/error-codes.js +104 -0
  7. package/lib/infra.js +569 -0
  8. package/lib/llm-wiki.js +109 -0
  9. package/lib/safe-rm.js +94 -0
  10. package/lib/scraper-utils.js +165 -0
  11. package/package.json +37 -5
  12. package/plugins/fancy-analyze/command-input.js +65 -0
  13. package/plugins/fancy-analyze/index.js +973 -0
  14. package/plugins/fancy-analyze/schema-analyze.md +379 -0
  15. package/plugins/fancy-analyze/schema-write.md +178 -0
  16. package/plugins/fancy-analyze/scripts/split_source.js +292 -0
  17. package/plugins/fancy-analyze/summary-progress.js +431 -0
  18. package/plugins/fancy-analyze/templates.js +881 -0
  19. package/plugins/fancy-bootstrap/index.js +168 -0
  20. package/plugins/fancy-bootstrap/scripts/init.js +143 -0
  21. package/plugins/fancy-bootstrap/scripts/path-utils.js +21 -0
  22. package/plugins/fancy-bootstrap/templates.js +54 -0
  23. package/plugins/fancy-import/import-core.js +1118 -0
  24. package/plugins/fancy-import/import-driver.js +581 -0
  25. package/plugins/fancy-import/index.js +730 -0
  26. package/plugins/fancy-import/prompts/01-import-prompt.md +106 -0
  27. package/plugins/fancy-import/templates.js +49 -0
  28. package/plugins/fancy-scan/index.js +319 -0
  29. package/plugins/fancy-scan/scripts/run-scan.js +520 -0
  30. package/plugins/fancy-scan/scripts/scrapers/fanqie-rank-scraper.js +794 -0
  31. package/plugins/fancy-scan/scripts/scrapers/jjwxc-rank-scraper.js +339 -0
  32. package/plugins/fancy-scan/scripts/scrapers/qimao-rank-scraper.js +611 -0
  33. package/plugins/fancy-scan/templates.js +295 -0
  34. package/plugins/fancy-story-builder/deploy-manifest.js +239 -0
  35. package/plugins/fancy-story-builder/deslop-driver.js +821 -0
  36. package/plugins/fancy-story-builder/flesh-output.js +155 -0
  37. package/plugins/fancy-story-builder/index.js +3152 -0
  38. package/plugins/fancy-story-builder/prompts/01-skeleton-prompt.md +553 -0
  39. package/plugins/fancy-story-builder/prompts/02-flesh-prompt.md +540 -0
  40. package/plugins/fancy-story-builder/prompts/03-rhythm-prompt.md +504 -0
  41. package/plugins/fancy-story-builder/prompts/04-writing-prompt.md +188 -0
  42. package/plugins/fancy-story-builder/prompts/05-deslop-prompt.md +96 -0
  43. package/plugins/fancy-story-builder/purpose-template.md +107 -0
  44. package/plugins/fancy-story-builder/references/formulas-rhythm.json +302 -0
  45. package/plugins/fancy-story-builder/references/formulas-skeleton.json +229 -0
  46. package/plugins/fancy-story-builder/references/glossary.md +585 -0
  47. package/plugins/fancy-story-builder/references/index.md +490 -0
  48. package/plugins/fancy-story-builder/references//345/206/231/344/275/234/346/214/207/345/257/274/00-index.md +174 -0
  49. package/plugins/fancy-story-builder/references//345/206/231/344/275/234/346/214/207/345/257/274/01-scene.md +150 -0
  50. package/plugins/fancy-story-builder/references//345/206/231/344/275/234/346/214/207/345/257/274/02-chapter-workflow.md +99 -0
  51. package/plugins/fancy-story-builder/references//345/206/231/344/275/234/346/214/207/345/257/274/03-opening-chapter.md +104 -0
  52. package/plugins/fancy-story-builder/references//345/206/231/344/275/234/346/214/207/345/257/274/04-dialogue-mastery.md +274 -0
  53. package/plugins/fancy-story-builder/references//345/206/231/344/275/234/346/214/207/345/257/274/05-genre-formulas.md +432 -0
  54. package/plugins/fancy-story-builder/references//345/206/231/344/275/234/346/214/207/345/257/274/06-tone-ensemble.md +259 -0
  55. package/plugins/fancy-story-builder/references//345/206/231/344/275/234/346/214/207/345/257/274/07-ledger-audit.md +222 -0
  56. package/plugins/fancy-story-builder/references//345/206/231/344/275/234/346/214/207/345/257/274/08-diagnosis-revision.md +205 -0
  57. package/plugins/fancy-story-builder/references//345/206/231/344/275/234/346/214/207/345/257/274/09-reading-power.md +135 -0
  58. package/plugins/fancy-story-builder/references//345/206/231/344/275/234/346/214/207/345/257/274/10-deslop.md +129 -0
  59. package/plugins/fancy-story-builder/references//350/212/202/345/245/217/346/214/207/345/257/274/00-index.md +98 -0
  60. package/plugins/fancy-story-builder/references//350/212/202/345/245/217/346/214/207/345/257/274/01-upgrade-rhythm.md +300 -0
  61. package/plugins/fancy-story-builder/references//350/212/202/345/245/217/346/214/207/345/257/274/02-arc-rhythm.md +168 -0
  62. package/plugins/fancy-story-builder/references//350/212/202/345/245/217/346/214/207/345/257/274/03-highpoint-hooks.md +189 -0
  63. package/plugins/fancy-story-builder/references//350/212/202/345/245/217/346/214/207/345/257/274/04-satisfaction.md +226 -0
  64. package/plugins/fancy-story-builder/references//350/212/202/345/245/217/346/214/207/345/257/274/05-foreshadow-density.md +195 -0
  65. package/plugins/fancy-story-builder/references//350/212/202/345/245/217/346/214/207/345/257/274/06-chapter-outline.md +226 -0
  66. package/plugins/fancy-story-builder/references//350/212/202/345/245/217/346/214/207/345/257/274/07-audit.md +163 -0
  67. package/plugins/fancy-story-builder/references//350/241/200/350/202/211/346/214/207/345/257/274/00-index.md +100 -0
  68. package/plugins/fancy-story-builder/references//350/241/200/350/202/211/346/214/207/345/257/274/01-character.md +239 -0
  69. package/plugins/fancy-story-builder/references//350/241/200/350/202/211/346/214/207/345/257/274/02-worldbuilding.md +245 -0
  70. package/plugins/fancy-story-builder/references//350/241/200/350/202/211/346/214/207/345/257/274/03-relations.md +181 -0
  71. package/plugins/fancy-story-builder/references//350/241/200/350/202/211/346/214/207/345/257/274/04-emotion-methods.md +286 -0
  72. package/plugins/fancy-story-builder/references//350/241/200/350/202/211/346/214/207/345/257/274/05-audit.md +177 -0
  73. package/plugins/fancy-story-builder/references//351/252/250/346/236/266/346/214/207/345/257/274/00-index.md +91 -0
  74. package/plugins/fancy-story-builder/references//351/252/250/346/236/266/346/214/207/345/257/274/01-positioning.md +208 -0
  75. package/plugins/fancy-story-builder/references//351/252/250/346/236/266/346/214/207/345/257/274/02-packaging.md +135 -0
  76. package/plugins/fancy-story-builder/references//351/252/250/346/236/266/346/214/207/345/257/274/03-entities.md +305 -0
  77. package/plugins/fancy-story-builder/references//351/252/250/346/236/266/346/214/207/345/257/274/04-conflict.md +328 -0
  78. package/plugins/fancy-story-builder/references//351/252/250/346/236/266/346/214/207/345/257/274/05-quota.md +187 -0
  79. package/plugins/fancy-story-builder/references//351/252/250/346/236/266/346/214/207/345/257/274/06-audit.md +142 -0
  80. package/plugins/fancy-story-builder/rhythm-output.js +140 -0
  81. package/plugins/fancy-story-builder/schema-setting.md +324 -0
  82. package/plugins/fancy-story-builder/scripts/ai-patterns.js +619 -0
  83. package/plugins/fancy-story-builder/scripts/check-guide-compliance.js +289 -0
  84. package/plugins/fancy-story-builder/scripts/content-quality.js +413 -0
  85. package/plugins/fancy-story-builder/scripts/deslop-validate.js +143 -0
  86. package/plugins/fancy-story-builder/scripts/error-classes.js +112 -0
  87. package/plugins/fancy-story-builder/scripts/flesh-validate.js +1189 -0
  88. package/plugins/fancy-story-builder/scripts/formula-engine.js +112 -0
  89. package/plugins/fancy-story-builder/scripts/graph-utils.js +1385 -0
  90. package/plugins/fancy-story-builder/scripts/label-coverage.js +171 -0
  91. package/plugins/fancy-story-builder/scripts/prompt-drift-check.js +441 -0
  92. package/plugins/fancy-story-builder/scripts/reading-power.js +298 -0
  93. package/plugins/fancy-story-builder/scripts/rhythm-validate.js +1216 -0
  94. package/plugins/fancy-story-builder/scripts/semantic-lint.js +377 -0
  95. package/plugins/fancy-story-builder/scripts/skeleton-quota.js +145 -0
  96. package/plugins/fancy-story-builder/scripts/skeleton-validate.js +1832 -0
  97. package/plugins/fancy-story-builder/scripts/stage-batches.js +1371 -0
  98. package/plugins/fancy-story-builder/scripts/stage-contract.js +417 -0
  99. package/plugins/fancy-story-builder/scripts/upstream-query.js +198 -0
  100. package/plugins/fancy-story-builder/scripts/writing-rules.js +167 -0
  101. package/plugins/fancy-story-builder/scripts/writing-validate.js +682 -0
  102. package/plugins/fancy-story-builder/skeleton-output.js +199 -0
  103. package/plugins/fancy-story-builder/stage-driver.js +1049 -0
  104. package/plugins/fancy-story-builder/templates//350/212/202/345/245/217//346/227/266/345/272/217/346/230/240/345/260/204/346/250/241/346/235/277.json +204 -0
  105. package/plugins/fancy-story-builder/templates//350/212/202/345/245/217//347/253/240/350/212/202/347/273/206/347/272/262/346/250/241/346/235/277.json +34 -0
  106. package/plugins/fancy-story-builder/templates//350/212/202/345/245/217//347/253/240/350/212/202/350/247/204/345/210/222/346/250/241/346/235/277.json +24 -0
  107. package/plugins/fancy-story-builder/templates//350/212/202/345/245/217//350/212/202/345/245/217/345/217/202/346/225/260/346/250/241/346/235/277.json +27 -0
  108. package/plugins/fancy-story-builder/templates//350/241/200/350/202/211//344/270/226/347/225/214/350/247/202/350/247/204/345/210/231/346/250/241/346/235/277.json +66 -0
  109. package/plugins/fancy-story-builder/templates//350/241/200/350/202/211//345/205/263/351/224/256/351/201/223/345/205/267/346/250/241/346/235/277.json +76 -0
  110. package/plugins/fancy-story-builder/templates//350/241/200/350/202/211//345/206/262/347/252/201/346/250/241/346/235/277.json +72 -0
  111. package/plugins/fancy-story-builder/templates//350/241/200/350/202/211//345/211/247/346/203/205/346/250/241/346/235/277.json +37 -0
  112. package/plugins/fancy-story-builder/templates//350/241/200/350/202/211//345/212/277/345/212/233/346/250/241/346/235/277.json +53 -0
  113. package/plugins/fancy-story-builder/templates//350/241/200/350/202/211//345/234/260/347/202/271/346/250/241/346/235/277.json +40 -0
  114. package/plugins/fancy-story-builder/templates//350/241/200/350/202/211//347/273/223/345/261/200/346/250/241/346/235/277.json +79 -0
  115. package/plugins/fancy-story-builder/templates//350/241/200/350/202/211//350/247/222/350/211/262/346/250/241/346/235/277.json +132 -0
  116. package/plugins/fancy-story-builder/templates//351/252/250/346/236/266//345/205/263/347/263/273/346/250/241/346/235/277.json +133 -0
  117. package/plugins/fancy-story-builder/templates//351/252/250/346/236/266//345/256/236/344/275/223/346/250/241/346/235/277.json +160 -0
  118. package/plugins/fancy-story-builder/templates//351/252/250/346/236/266//345/261/202/347/272/247/346/250/241/346/235/277.json +65 -0
  119. package/plugins/fancy-story-builder/templates//351/252/250/346/236/266//346/241/206/346/236/266/346/250/241/346/235/277.json +134 -0
  120. package/plugins/fancy-story-builder/templates.js +1248 -0
  121. package/plugins/fancy-story-builder/wiki-references.js +204 -0
  122. package/plugins/fancy-story-builder/writing-driver.js +1061 -0
  123. package/plugins/fancy-topic/index.js +704 -0
  124. package/plugins/fancy-topic/scripts/select-topic.js +274 -0
  125. package/plugins/fancy-topic/templates.js +373 -0
  126. package/commands/bootstrap/index.js +0 -164
  127. package/commands/bootstrap/init-project.js +0 -121
  128. package/commands/scan/index.js +0 -283
  129. package/commands/scan/platforms/fanqie.js +0 -146
  130. package/commands/scan/platforms/jinjiang.js +0 -143
  131. package/commands/scan/platforms/qidian.js +0 -102
  132. package/commands/scan/platforms/qimao.js +0 -127
  133. package/commands/scan/scraper.js +0 -195
  134. package/infra.js +0 -160
@@ -0,0 +1,155 @@
1
+ /**
2
+ * flesh-output.js —— 血肉阶段的产出盘点
3
+ *
4
+ * 背景(2026-10 tt5 产物复查):
5
+ * 血肉阶段是一次性派活:插件把整个血肉提示词投给 LLM,让它在一个回合里
6
+ * 依次产出 8 个 JSON。真实规模下这个回合的产出量是
7
+ * 角色 166KB + 冲突 81KB + 势力 20KB + 剧情 7KB + 地点 22KB
8
+ * + 世界观规则 17KB + 关键道具 23KB ≈ 336KB(十几万 token 的输出)。
9
+ * 回合预算必然在中途耗尽。
10
+ *
11
+ * 实测 tt5:7 个文件产出,结局.json 没产出,.stage-status.json 的
12
+ * all_check 一直是 PENDING(全量校验从未跑过),而插件这边早就返回了
13
+ * "血肉阶段开始" —— 用户看不到任何提示,整个阶段是**静默失败**的。
14
+ *
15
+ * 本模块负责回答两个问题:
16
+ * 1. 血肉阶段到底产出了哪几个文件?(缺哪几个)
17
+ * 2. 全量校验过了没有?(all_check 是不是 PASSED)
18
+ *
19
+ * 有了这两个事实,插件才能在阶段结束时给出**可执行**的结论,
20
+ * 而不是一句"阶段开始"就撒手。
21
+ */
22
+ import fs from 'node:fs';
23
+ import path from 'node:path';
24
+
25
+ // 血肉阶段的 8 个产出文件(顺序 = 提示词里的生成顺序,依赖关系见 02-flesh-prompt.md 第六节)
26
+ export const FLESH_OUTPUT_FILES = [
27
+ '角色.json',
28
+ '冲突.json',
29
+ '势力.json',
30
+ '剧情.json',
31
+ '地点.json',
32
+ '结局.json',
33
+ '世界观规则.json',
34
+ '关键道具.json'
35
+ ];
36
+
37
+ /**
38
+ * 盘点血肉阶段的产出。
39
+ *
40
+ * 返回:
41
+ * present 已产出的文件名(按 FLESH_OUTPUT_FILES 顺序)
42
+ * missing 缺失的文件名
43
+ * complete 8 个文件是否齐全
44
+ */
45
+ export function inspectFleshOutput(stageDir) {
46
+ const present = [];
47
+ const missing = [];
48
+ for (const f of FLESH_OUTPUT_FILES) {
49
+ const p = path.join(stageDir, f);
50
+ let ok = false;
51
+ try {
52
+ ok = fs.existsSync(p) && fs.statSync(p).size > 0;
53
+ } catch {
54
+ ok = false;
55
+ }
56
+ if (ok) present.push(f);
57
+ else missing.push(f);
58
+ }
59
+ return { present, missing, complete: missing.length === 0 };
60
+ }
61
+
62
+ /**
63
+ * 读血肉阶段的 .stage-status.json,看全量校验的状态。
64
+ *
65
+ * 返回 { allCheck, rounds, files, error }:
66
+ * allCheck: 'PASSED' | 'FAILED' | 'PENDING' | null(读不到就是 null)
67
+ * files: { 文件名: { status, retries } },单文件校验结果
68
+ * error: 读不到/解析失败的原因
69
+ */
70
+ export function readFleshStageStatus(stageDir) {
71
+ const p = path.join(stageDir, '.stage-status.json');
72
+ if (!fs.existsSync(p)) {
73
+ return { allCheck: null, rounds: 0, files: {}, error: '.stage-status.json 不存在(血肉阶段还没跑过校验)' };
74
+ }
75
+ let s;
76
+ try {
77
+ s = JSON.parse(fs.readFileSync(p, 'utf-8'));
78
+ } catch (e) {
79
+ return { allCheck: null, rounds: 0, files: {}, error: '.stage-status.json 解析失败:' + e.message };
80
+ }
81
+ if (!s || typeof s !== 'object') {
82
+ return { allCheck: null, rounds: 0, files: {}, error: '.stage-status.json 内容不是对象' };
83
+ }
84
+ const all = s.all_check && typeof s.all_check === 'object' ? s.all_check : {};
85
+ return {
86
+ allCheck: all.status || null,
87
+ rounds: all.rounds || 0,
88
+ files: (s.files && typeof s.files === 'object') ? s.files : {},
89
+ error: null
90
+ };
91
+ }
92
+
93
+ /**
94
+ * 生成血肉阶段收尾的结论说明(人类可读、可执行)。
95
+ *
96
+ * 覆盖四种情况:
97
+ * 1. 文件齐 + 全量 PASSED → 通过
98
+ * 2. 文件齐 + 全量没过 → 文件在,但跨文件一致性没验过
99
+ * 3. 文件缺 + 全量没过 → 阶段没跑完(最常见:回合预算耗尽)
100
+ * 4. 文件缺 + 全量 PASSED → 数据不一致,需要人工核对
101
+ */
102
+ export function buildFleshCompletionNote(inspect, status) {
103
+ const lines = [];
104
+ const allCheck = status.allCheck;
105
+ const missing = inspect.missing;
106
+
107
+ if (inspect.complete && allCheck === 'PASSED') {
108
+ lines.push('血肉阶段产出检查:8 个 JSON 齐全,全量校验(--all)已通过。');
109
+ lines.push('');
110
+ lines.push('产出文件:');
111
+ for (const f of inspect.present) lines.push('- 设定/raw/sources/血肉/' + f);
112
+ lines.push('');
113
+ lines.push('可以进入节奏阶段(节奏阶段的上游门禁要求血肉阶段 all_check.status = PASSED)。');
114
+ return lines.join('\n');
115
+ }
116
+
117
+ lines.push('血肉阶段产出检查:**未通过**,当前状态如下。');
118
+
119
+ if (!inspect.complete) {
120
+ lines.push('');
121
+ lines.push('- 缺失文件(' + missing.length + '/' + FLESH_OUTPUT_FILES.length + '):' + missing.join('、'));
122
+ lines.push(' 常见原因:血肉阶段是一次性派活,8 个文件要在一个回合里全部产出,');
123
+ lines.push(' 真实规模下输出量超过单回合预算,LLM 在中途耗尽预算就停了。');
124
+ } else {
125
+ lines.push('');
126
+ lines.push('- 8 个 JSON 都已产出。');
127
+ }
128
+
129
+ lines.push('');
130
+ if (allCheck === 'PASSED') {
131
+ lines.push('- 全量校验:PASSED(但文件集合与校验记录不一致,需要人工核对)。');
132
+ } else if (allCheck === 'FAILED') {
133
+ lines.push('- 全量校验:FAILED(跨文件一致性检查没过,错误见校验脚本输出)。');
134
+ } else if (allCheck === 'PENDING') {
135
+ lines.push('- 全量校验:**PENDING**(从未跑过 --all,跨文件一致性、配额一致性、引用完整性全都没验过)。');
136
+ } else {
137
+ lines.push('- 全量校验:**未运行**(' + (status.error || '状态不可读') + ')。');
138
+ }
139
+
140
+ lines.push('');
141
+ lines.push('下一步:');
142
+ if (!inspect.complete) {
143
+ lines.push('1. 重新运行血肉阶段,补齐缺失文件:' + missing.join('、'));
144
+ lines.push('2. 8 个文件齐了之后,必须再跑一次全量校验(--all),确认 all_check.status = PASSED;');
145
+ lines.push('3. 在此之前不要进入节奏阶段 —— 节奏阶段的上游门禁要求血肉阶段全量校验通过。');
146
+ } else {
147
+ lines.push('1. 跑一次全量校验(--all),把 errors 逐条改掉;');
148
+ lines.push('2. 直到 all_check.status = PASSED 再进入节奏阶段。');
149
+ }
150
+ lines.push('');
151
+ lines.push('> 注意:血肉阶段目前**没有**断点续跑机制,重跑会覆盖已有文件(这是有意为之:');
152
+ lines.push('> 血肉产物要求 id/name 与骨架严格一致,旧文件带着上一轮的措辞,整体覆盖比增量修补更安全)。');
153
+
154
+ return lines.join('\n');
155
+ }