@cloud411716/fancy-webnovel 2.2.0 → 3.0.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 (211) hide show
  1. package/client.js +201 -15
  2. package/cordis.patch.yml +5 -0
  3. package/docs/douyin-plugin.md +118 -0
  4. package/docs/material-library/README.md +404 -0
  5. package/docs/material-library/import.js +437 -0
  6. package/docs/material-library/prompt.md +370 -0
  7. package/docs/material-library/queries.surql +94 -0
  8. package/docs/material-library/sample.jsonl +14 -0
  9. package/docs/material-library/schema.surql +46 -0
  10. package/docs/mcp-profile.example.yml +24 -0
  11. package/docs/story-graph-design.md +602 -0
  12. package/docs/story-graph-validation.md +81 -0
  13. package/docs/workspace-mcp.md +284 -0
  14. package/index.js +11 -7
  15. package/lib/atomic-write.js +109 -0
  16. package/lib/chapter-order.js +100 -0
  17. package/lib/confirmation.js +80 -0
  18. package/lib/db-init.js +123 -0
  19. package/lib/deployed-state.js +11 -11
  20. package/lib/direction-labels.js +265 -0
  21. package/lib/error-codes.js +31 -31
  22. package/lib/infra.js +29 -4
  23. package/lib/material-db.js +149 -0
  24. package/lib/path-guard.js +150 -0
  25. package/lib/projects.js +400 -0
  26. package/lib/scraper-utils.js +140 -0
  27. package/lib/surreal-server.js +338 -0
  28. package/lib/topic-decision.js +860 -0
  29. package/lib/topic-fields.js +251 -0
  30. package/lib/topic-schema.js +225 -0
  31. package/lib/workspace.js +501 -0
  32. package/package.json +29 -4
  33. package/plugins/fancy-analyze/analyze-definitions.md +519 -0
  34. package/plugins/fancy-analyze/index.js +1128 -77
  35. package/plugins/fancy-analyze/ingest-coverage.js +107 -0
  36. package/plugins/fancy-analyze/schema-analyze.md +355 -107
  37. package/plugins/fancy-analyze/scripts/append-summary-chapter.js +612 -0
  38. package/plugins/fancy-analyze/summary-progress.js +71 -7
  39. package/plugins/fancy-analyze/templates.js +437 -139
  40. package/plugins/fancy-bootstrap/index.js +276 -131
  41. package/plugins/fancy-bootstrap/scripts/init.js +59 -25
  42. package/plugins/fancy-bootstrap/templates.js +35 -18
  43. package/plugins/fancy-db/index.js +172 -0
  44. package/plugins/fancy-douyin/deploy.js +134 -0
  45. package/plugins/fancy-douyin/index.js +551 -0
  46. package/plugins/fancy-douyin/prompts/01-analysis-prompt.md +84 -0
  47. package/plugins/fancy-douyin/scripts/crawl-note.cjs +194 -0
  48. package/plugins/fancy-douyin/scripts/lib.cjs +197 -0
  49. package/plugins/fancy-douyin/scripts/scan-account.cjs +128 -0
  50. package/plugins/fancy-douyin/scripts/start-chrome.cjs +203 -0
  51. package/plugins/fancy-douyin/state.js +197 -0
  52. package/plugins/fancy-douyin/templates.js +127 -0
  53. package/plugins/fancy-export/exporter.js +805 -0
  54. package/plugins/fancy-export/index.js +63 -0
  55. package/plugins/fancy-import/import-driver.js +29 -6
  56. package/plugins/fancy-import/index.js +13 -5
  57. package/plugins/fancy-import/prompts/01-import-prompt.md +39 -14
  58. package/plugins/fancy-import/templates.js +17 -8
  59. package/plugins/fancy-material/exporter.js +153 -0
  60. package/plugins/fancy-material/genres.js +256 -0
  61. package/plugins/fancy-material/index.js +835 -0
  62. package/plugins/fancy-material/inventory.js +143 -0
  63. package/plugins/fancy-material/kinds.js +313 -0
  64. package/plugins/fancy-material/queue.js +55 -0
  65. package/plugins/fancy-material/scripts/query.js +254 -0
  66. package/plugins/fancy-material/templates.js +258 -0
  67. package/plugins/fancy-material/tool-deploy.js +138 -0
  68. package/plugins/fancy-material/validate.js +149 -0
  69. package/plugins/fancy-project/index.js +133 -0
  70. package/plugins/fancy-scan/existing-block.js +100 -0
  71. package/plugins/fancy-scan/index.js +410 -21
  72. package/plugins/fancy-scan/prompts/01-analysis-prompt.md +302 -0
  73. package/plugins/fancy-scan/scripts/append-block.js +725 -0
  74. package/plugins/fancy-scan/scripts/report-validate.js +824 -0
  75. package/plugins/fancy-scan/scripts/run-scan.js +169 -22
  76. package/plugins/fancy-scan/scripts/scrapers/fanqie-rank-scraper.js +145 -16
  77. package/plugins/fancy-scan/scripts/scrapers/jjwxc-rank-scraper.js +179 -49
  78. package/plugins/fancy-scan/scripts/scrapers/qimao-rank-scraper.js +38 -20
  79. package/plugins/fancy-scan/templates/blocks.js +155 -0
  80. package/plugins/fancy-scan/templates/platforms.js +372 -0
  81. package/plugins/fancy-scan/templates/report-schema.js +90 -0
  82. package/plugins/fancy-scan/templates.js +545 -146
  83. package/plugins/fancy-scan/tool-deploy.js +335 -0
  84. package/plugins/fancy-scan/wait-turn.js +46 -0
  85. package/plugins/fancy-story-builder/db/README.md +106 -0
  86. package/plugins/fancy-story-builder/db/client.js +228 -0
  87. package/plugins/fancy-story-builder/db/commands.js +145 -0
  88. package/plugins/fancy-story-builder/db/ids.js +39 -0
  89. package/plugins/fancy-story-builder/db/import.js +798 -0
  90. package/plugins/fancy-story-builder/db/project.js +299 -0
  91. package/plugins/fancy-story-builder/db/query.js +361 -0
  92. package/plugins/fancy-story-builder/db/schema.js +417 -0
  93. package/plugins/fancy-story-builder/db/stage-sync.js +238 -0
  94. package/plugins/fancy-story-builder/flesh-output.js +19 -6
  95. package/plugins/fancy-story-builder/index.js +4105 -396
  96. package/plugins/fancy-story-builder/patch-driver.js +390 -0
  97. package/plugins/fancy-story-builder/prompts/01-skeleton-prompt.md +29 -19
  98. package/plugins/fancy-story-builder/prompts/02-flesh-prompt.md +72 -10
  99. package/plugins/fancy-story-builder/prompts/03-rhythm-prompt.md +40 -5
  100. package/plugins/fancy-story-builder/prompts/04-writing-prompt.md +37 -0
  101. package/plugins/fancy-story-builder/purpose-template.md +42 -66
  102. package/plugins/fancy-story-builder/references/formulas-skeleton.json +229 -56
  103. package/plugins/fancy-story-builder/references/genre-profiles.json +3514 -0
  104. package/plugins/fancy-story-builder/references/glossary.md +15 -6
  105. package/plugins/fancy-story-builder/references/index.md +97 -6
  106. package/plugins/fancy-story-builder/references//350/212/202/345/245/217/346/214/207/345/257/274/00-index.md +1 -1
  107. package/plugins/fancy-story-builder/references//350/212/202/345/245/217/346/214/207/345/257/274/07-audit.md +25 -7
  108. package/plugins/fancy-story-builder/references//350/241/200/350/202/211/346/214/207/345/257/274/01-character.md +5 -1
  109. package/plugins/fancy-story-builder/references//350/241/200/350/202/211/346/214/207/345/257/274/03-relations.md +6 -2
  110. package/plugins/fancy-story-builder/references//350/241/200/350/202/211/346/214/207/345/257/274/05-audit.md +15 -5
  111. package/plugins/fancy-story-builder/references//351/252/250/346/236/266/346/214/207/345/257/274/00-index.md +1 -1
  112. package/plugins/fancy-story-builder/references//351/252/250/346/236/266/346/214/207/345/257/274/01-positioning.md +2 -1
  113. package/plugins/fancy-story-builder/references//351/252/250/346/236/266/346/214/207/345/257/274/03-entities.md +1 -1
  114. package/plugins/fancy-story-builder/references//351/252/250/346/236/266/346/214/207/345/257/274/06-audit.md +19 -1
  115. package/plugins/fancy-story-builder/schema-setting.json +1100 -0
  116. package/plugins/fancy-story-builder/schema-setting.md +201 -293
  117. package/plugins/fancy-story-builder/scripts/brief-validate.js +164 -0
  118. package/plugins/fancy-story-builder/scripts/content-quality.js +4 -1
  119. package/plugins/fancy-story-builder/scripts/flesh-validate.js +135 -12
  120. package/plugins/fancy-story-builder/scripts/graph-utils.js +146 -47
  121. package/plugins/fancy-story-builder/scripts/reference-log.js +110 -0
  122. package/plugins/fancy-story-builder/scripts/rhythm-validate.js +100 -4
  123. package/plugins/fancy-story-builder/scripts/schema-pages.js +2668 -0
  124. package/plugins/fancy-story-builder/scripts/semantic-lint.js +5 -1
  125. package/plugins/fancy-story-builder/scripts/skeleton-validate.js +158 -17
  126. package/plugins/fancy-story-builder/scripts/stage-batches.js +36 -2
  127. package/plugins/fancy-story-builder/scripts/stage-contract.js +12 -0
  128. package/plugins/fancy-story-builder/scripts/story-artifacts.js +933 -0
  129. package/plugins/fancy-story-builder/scripts/upstream-query.js +1 -1
  130. package/plugins/fancy-story-builder/scripts/v2/baseline.js +112 -0
  131. package/plugins/fancy-story-builder/scripts/v2/cast.js +517 -0
  132. package/plugins/fancy-story-builder/scripts/v2/context.js +434 -0
  133. package/plugins/fancy-story-builder/scripts/v2/contracts.js +493 -0
  134. package/plugins/fancy-story-builder/scripts/v2/core.js +419 -0
  135. package/plugins/fancy-story-builder/scripts/v2/engine.js +1068 -0
  136. package/plugins/fancy-story-builder/scripts/v2/export-markdown.js +794 -0
  137. package/plugins/fancy-story-builder/scripts/v2/genre.js +195 -0
  138. package/plugins/fancy-story-builder/scripts/v2/knowledge.js +321 -0
  139. package/plugins/fancy-story-builder/scripts/v2/macro.js +409 -0
  140. package/plugins/fancy-story-builder/scripts/v2/manifest.js +538 -0
  141. package/plugins/fancy-story-builder/scripts/v2/migrate.js +137 -0
  142. package/plugins/fancy-story-builder/scripts/v2/prompts.js +1335 -0
  143. package/plugins/fancy-story-builder/scripts/v2/rhythm.js +618 -0
  144. package/plugins/fancy-story-builder/scripts/v2/scale.js +843 -0
  145. package/plugins/fancy-story-builder/scripts/v2/snapshot.js +121 -0
  146. package/plugins/fancy-story-builder/scripts/v2/stages.js +273 -0
  147. package/plugins/fancy-story-builder/scripts/v2/writing.js +216 -0
  148. package/plugins/fancy-story-builder/storydb/README.md +271 -0
  149. package/plugins/fancy-story-builder/storydb/cli.js +458 -0
  150. package/plugins/fancy-story-builder/storydb/client.js +351 -0
  151. package/plugins/fancy-story-builder/storydb/compile.js +452 -0
  152. package/plugins/fancy-story-builder/storydb/context.js +288 -0
  153. package/plugins/fancy-story-builder/storydb/definitions.js +699 -0
  154. package/plugins/fancy-story-builder/storydb/driver.js +106 -0
  155. package/plugins/fancy-story-builder/storydb/dsh-tools.js +313 -0
  156. package/plugins/fancy-story-builder/storydb/export.js +175 -0
  157. package/plugins/fancy-story-builder/storydb/ids.js +31 -0
  158. package/plugins/fancy-story-builder/storydb/impact.js +170 -0
  159. package/plugins/fancy-story-builder/storydb/import.js +559 -0
  160. package/plugins/fancy-story-builder/storydb/mcp.js +99 -0
  161. package/plugins/fancy-story-builder/storydb/prompts.js +952 -0
  162. package/plugins/fancy-story-builder/storydb/stage-command.js +379 -0
  163. package/plugins/fancy-story-builder/storydb/stage.js +426 -0
  164. package/plugins/fancy-story-builder/storydb/store.js +891 -0
  165. package/plugins/fancy-story-builder/storydb/tools.js +592 -0
  166. package/plugins/fancy-story-builder/storydb/validation.js +183 -0
  167. package/plugins/fancy-story-builder/templates/v2/10-scale/scale-template.json +144 -0
  168. package/plugins/fancy-story-builder/templates/v2/20-macro/emotion-template.json +15 -0
  169. package/plugins/fancy-story-builder/templates/v2/20-macro/endings-template.json +16 -0
  170. package/plugins/fancy-story-builder/templates/v2/20-macro/lines-template.json +28 -0
  171. package/plugins/fancy-story-builder/templates/v2/20-macro/roles-template.json +10 -0
  172. package/plugins/fancy-story-builder/templates/v2/20-macro/story-template.json +19 -0
  173. package/plugins/fancy-story-builder/templates/v2/20-macro/volumes-template.json +24 -0
  174. package/plugins/fancy-story-builder/templates/v2/20-macro/world-template.json +24 -0
  175. package/plugins/fancy-story-builder/templates/v2/30-cast/characters-template.json +49 -0
  176. package/plugins/fancy-story-builder/templates/v2/30-cast/climaxes-template.json +14 -0
  177. package/plugins/fancy-story-builder/templates/v2/30-cast/conflicts-template.json +30 -0
  178. package/plugins/fancy-story-builder/templates/v2/30-cast/factions-template.json +18 -0
  179. package/plugins/fancy-story-builder/templates/v2/30-cast/foreshadows-template.json +29 -0
  180. package/plugins/fancy-story-builder/templates/v2/30-cast/information-template.json +29 -0
  181. package/plugins/fancy-story-builder/templates/v2/30-cast/items-template.json +13 -0
  182. package/plugins/fancy-story-builder/templates/v2/30-cast/locations-template.json +12 -0
  183. package/plugins/fancy-story-builder/templates/v2/30-cast/payoffs-template.json +16 -0
  184. package/plugins/fancy-story-builder/templates/v2/30-cast/relations-template.json +44 -0
  185. package/plugins/fancy-story-builder/templates/v2/40-rhythm/chapter-map-template.json +81 -0
  186. package/plugins/fancy-story-builder/templates/v2/40-rhythm/outline-template.json +162 -0
  187. package/plugins/fancy-story-builder/templates/v2/50-writing/ledger-template.json +46 -0
  188. package/plugins/fancy-story-builder/templates/v2/60-deslop/report-template.json +10 -0
  189. 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 +267 -44
  190. 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 +121 -19
  191. 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 +129 -21
  192. package/plugins/fancy-story-builder/templates//350/241/200/350/202/211//345/205/266/344/273/226/345/256/236/344/275/223/346/250/241/346/235/277.json +62 -0
  193. 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 +76 -17
  194. 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 +56 -8
  195. 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 +63 -13
  196. 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 +34 -6
  197. 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 +81 -18
  198. 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 +202 -42
  199. 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 +160 -27
  200. 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 +217 -41
  201. 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 +215 -41
  202. package/plugins/fancy-story-builder/templates.js +272 -74
  203. package/plugins/fancy-story-builder/wiki-references.js +429 -93
  204. package/plugins/fancy-story-builder/writing-driver.js +336 -9
  205. package/plugins/fancy-topic/index.js +414 -61
  206. package/plugins/fancy-topic/prompts/01-exploration-prompt.md +115 -0
  207. package/plugins/fancy-topic/scripts/save-suggestion.js +219 -0
  208. package/plugins/fancy-topic/scripts/select-topic.js +106 -63
  209. package/plugins/fancy-topic/templates.js +225 -122
  210. package/plugins/fancy-topic/tool-deploy.js +200 -0
  211. package/lib/safe-rm.js +0 -94
@@ -0,0 +1,370 @@
1
+ ## 一、角色与写作原则
2
+
3
+ 你是一位跨媒介故事素材设计师。你不写完整小说,而是生产**可以独立取用、自由组合**的小块素材。
4
+
5
+ 你的判断标准来自成熟的写作训练,而不是“多写形容词”:
6
+
7
+ - **具体优先**:具体名词、具体动作、具体数字,优先于抽象形容词。(参考《The Elements of Style》的“省略不必要的词、用具体语言”)
8
+ - **少而准**:一段描写只需要几个能代表整体的细节,不要从头到脚列清单。(参考 Stephen King《On Writing》)
9
+ - **展示而不是告知**:用动作、物件、反应、感官让读者自己判断,不要直接写“他很善良”“她很美丽”。(参考 Stephen King、McKee《Story》)
10
+ - **场景要转向**:一个场景里必须有目标、阻碍、转折,结束时某个价值发生变化;没有变化的场景是说明,不是场景。(参考 Robert McKee《Story》)
11
+ - **冲突要升级**:人物想要什么、怕失去什么、为什么不能退;每次选择都要付出更大代价。
12
+ - **人物要有欲望、缺陷、秘密**:没有缺陷和秘密的人物立不住;缺陷要能制造麻烦,而不是装饰。(参考《短篇小说写作指南》《小说写作:叙事技巧指南》)
13
+ - **五感交叠**:声音、气味、触感、温度、光线至少占两三种;不要只写“阴森恐怖”。(参考《这样写出好故事:描写与背景》)
14
+ - **细节分类**:肖像、动作、心理、景物、道具,每类都可以成为独立素材;一条素材只负责一个细节。
15
+ - **伏笔要回收**:埋下的线索必须有强化、误导、揭示和兑现;不要写“埋下一个秘密”就结束。
16
+ - **对白有潜台词**:人物说的和想的不能完全一样;不要让角色把设定念出来。
17
+ - **留白**:描写在作者脑中开始,在读者脑中完成;不要把每个缝隙都填满。
18
+
19
+ 如果 `{{STYLE_RULES}}` 不是“未指定”,在不违背以上原则的前提下遵循该风格规则。
20
+
21
+ 当前风格规则:{{STYLE_RULES}}
22
+
23
+ ---
24
+
25
+ ## 二、原子素材模型
26
+
27
+ 一条素材 = 一个小积木,只回答一个小问题。
28
+
29
+ ```json
30
+ {
31
+ "id": "place_name_gui_xu_v4",
32
+ "kind": "place_name",
33
+ "name": "归墟",
34
+ "tags": ["地名", "海", "尽头", "仙侠", "不祥"],
35
+ "genres": ["仙侠", "通用"],
36
+ "note": "",
37
+ "source": "builtin"
38
+ }
39
+ ```
40
+
41
+ 公共字段有七个:
42
+
43
+ | 字段 | 必填 | 说明 |
44
+ | --- | --- | --- |
45
+ | `id` | 是 | `<kind>_<ascii_slug>_v4`,全局唯一 |
46
+ | `kind` | 是 | 下面素材类型总表之一;builtin 素材必须在表内 |
47
+ | `name` | 是 | **素材本体**:名字、短语、一句话机制/代价/规则/钩子 |
48
+ | `tags` | 是 | 3–8 个短标签,用于检索和组合 |
49
+ | `genres` | 是 | 1–3 个适用题材;跨题材写 `["通用"]` |
50
+ | `note` | 否 | 只有 `name` 不够清楚时补一句,默认空字符串 |
51
+ | `source` | 是 | `builtin` 或 `other`;本次生成的素材固定写 `builtin` |
52
+
53
+ 不要新增 `summary`、`description`、`core_hook`、`market_diff`、`payload`、`sources` 等字段。
54
+
55
+ `name` 不是标题,而是素材本身:
56
+
57
+ ```text
58
+ given_name → 砚秋
59
+ color_word → 被雨泡过的朱砂
60
+ ability_mechanism → 触碰死者眼睛,进入他死前最后24分钟的主观视角
61
+ ability_cost → 每次使用后永久丢失一段与死者无关的等长记忆
62
+ conflict_seed → 妻子要保险金救女儿,主角要证明她杀了丈夫
63
+ brainstorm → 给活人打印死亡证明的打印店
64
+ ```
65
+
66
+ ---
67
+
68
+ ## 三、素材类型总表
69
+
70
+ {{KIND_TABLE}}
71
+
72
+ ---
73
+
74
+ ## 四、本批生成范围
75
+
76
+ {{FOCUS_BLOCK}}
77
+
78
+ **顺序要求**:一个批次只写一个 kind。插件会在「本次运行」里指定本批 kind 和本批条数;写满本批条数后立即结束本轮,不要自己切换到下一个 kind,也不要等插件再次提醒。插件会自动发送下一批,直到该 kind 达到目标数量。
79
+
80
+ ---
81
+
82
+ ## 五、质量红线(必须执行)
83
+
84
+ 一条素材只有满足以下至少 4 条才允许输出:
85
+
86
+ 1. **具体**:能在 30 秒内想象成一个画面、动作、规则或人物关系。
87
+ 2. **可复用**:不绑定某个具体人物、武器、门派或章节。
88
+ 3. **有信息**:不是“火红、淡红、蓝色、耀眼、璀璨、神秘、强大”这类词典词。
89
+ 4. **有质感**:至少包含一个具体参照物、感官来源、情绪或处境。
90
+ 5. **有文笔**:不是网络热词,不是成语堆砌,不超过一句,不写散文。
91
+ 6. **有差异**:和已有素材不是同义换皮。
92
+
93
+ 如果一条素材删掉后正文没有任何损失,就不收。
94
+
95
+ ### 5.1 描写词专项标准
96
+
97
+ 颜色、光影、声音、气味、触感、特效词,必须满足至少 4 条:
98
+
99
+ - 有具体参照物:不是纯色,而是“某物上的颜色/光/声音”。
100
+ - 有感官来源:材质、光源、天气、时间、温度、动作至少占一个。
101
+ - 有情绪或处境:冷、旧、危险、廉价、神圣、脏、病态、压迫。
102
+ - 能脱离原句独立使用。
103
+ - 不是常见词典搭配或网络热词。
104
+
105
+ **直接废弃**:
106
+
107
+ ```text
108
+ 火红、血红、淡红、深红、鲜红、红彤彤
109
+ 蓝蓝的、雪白、漆黑
110
+ 耀眼、璀璨、绚丽、美丽
111
+ 神秘、强大、古老
112
+ 淡淡的红、微微发蓝、有一点红
113
+ ```
114
+
115
+ **可以入库**:
116
+
117
+ ```text
118
+ 被雨泡过的朱砂
119
+ 旧戏台幕布褪下来的胭脂红
120
+ 铁锈里透出的一线暗红
121
+ 火葬场烟囱口被灰压住的橘红
122
+ 冷白灯下显得发黑的枣红
123
+ 停尸柜不锈钢上凝出的青蓝
124
+ 旧玻璃瓶底那种发绿的蓝
125
+ 雨夜路灯下被水洼打碎的钴蓝
126
+ 像有人把月光折成细线
127
+ 碎成细屑的冷白
128
+ 像湿纸被迅速撕开
129
+ 指甲刮过瓷面
130
+ ```
131
+
132
+ 要求:
133
+
134
+ - 2–12 字优先;超过一句的描写词不收。
135
+ - 一条只写一个画面,不要“像 A 又像 B 还像 C”堆砌。
136
+ - 同义换皮只保留最好的一条。
137
+
138
+ ### 5.2 各类素材的额外要求
139
+
140
+ - **名字类**:不要“张三、李四、王强、林婉儿”这种大路货;要有语感、含义或画面;不撞真实人物和已有作品专名。
141
+ - **人物属性**:不要“善良、美丽、沉稳、高强”;写可观察的细节,例如“越紧张越爱整理袖口”。
142
+ - **能力机制/代价**:不要“系统面板、无限复制、神秘力量”;机制、代价、限制、反制分别成条。
143
+ - **物品**:不要“神秘宝剑、古老法器”;外形、材质、功能、视觉特征分别成条。
144
+ - **场景/感官**:不要“阴森恐怖、美丽壮观”;写具体声音、气味、温度、光线、物件。
145
+ - **脑洞/剧情**:不要“神秘组织、古老秘密、命运安排”;写具体高概念、双方目标、规则、钩子。
146
+ - **模板**:模板必须能直接套用,不能只是“要写得有画面感”这种空话。
147
+
148
+ ### 5.3 命名类专项标准(人名、地名、组织名、能力名、物品名、怪物名、神话生物/神祇名)
149
+
150
+ 命名类素材必须至少满足 3 条:
151
+
152
+ 1. **有具体锚点**:数字、地名、材质、动作、职业、年代、禁忌、功能、反差,至少占一个。
153
+ 2. **能让人追问“为什么叫这个”**:名字背后有故事、来历、规则或代价。
154
+ 3. **不是“形容词 + 通用名词”**:例如“旧仓单”“黑色长刀”“神秘古卷”这种没有信息量的组合。
155
+ 4. **不是“功能标签 + 身体部位”**:例如“复原眼”“章眼”“读心手”这种一眼看穿、没有余味的命名。
156
+ 5. **有音感和字形记忆点**:读起来不绕口,写出来不撞常见网文名。
157
+ 6. **不撞真实人物、真实品牌、真实作品专名。**
158
+
159
+ **直接废弃**:
160
+
161
+ ```text
162
+ 复原眼
163
+ 章眼
164
+ 读心手
165
+ 旧仓单
166
+ 神秘剑
167
+ 古老法袍
168
+ 破旧木箱
169
+ 黑色长刀
170
+ 王家老宅
171
+ ```
172
+
173
+ **可以入库**:
174
+
175
+ ```text
176
+ 回魂秤
177
+ 缺页仓单
178
+ 三号柜的铜牌
179
+ 缝尸针
180
+ 半枚虎符
181
+ 二十四帧瞳
182
+ 覆字印
183
+ 夜班窗口
184
+ 倒挂七筹
185
+ ```
186
+
187
+ 对物品名的额外要求:
188
+
189
+ - 必须能看出材质、年代、地点、数字、缺损、功能或主人痕迹中的至少一个。
190
+ - “旧仓单”只是“旧 + 仓单”,没有锚点;
191
+ “缺页仓单”“民国廿三年仓单”“盖错印的仓单”才有信息。
192
+ - 不要用“神秘、古老、强大、传说、绝世”当唯一卖点。
193
+
194
+ 对能力名的额外要求:
195
+
196
+ - 不要用“眼、手、心、脑”直接拼功能;
197
+ “复原眼”“章眼”太像功能标签,读者不会记住。
198
+ - 优先用具体意象、代价、来源或反差命名,例如“二十四帧瞳”“代息”“倒带瞳”。
199
+
200
+ 自检:
201
+
202
+ ```text
203
+ 如果这个名字可以无损失地替换成“东西”“能力”“地方”,它就是废名。
204
+ ```
205
+
206
+ ---
207
+
208
+ ## 六、标签与题材
209
+
210
+ ### `tags`
211
+
212
+ - 3–8 个短标签,不要写句子。
213
+ - 维度:题材、类型、功能、元素、情绪、场景、代价、关系、强度。
214
+ - 例:
215
+
216
+ ```text
217
+ ["男","青年","正派","沉稳","法医"]
218
+ ["红","暖色","强烈","火光"]
219
+ ["记忆","永久","关系代价","调查"]
220
+ ["宗门","雷系","执法","正派"]
221
+ ```
222
+
223
+ 不要用 `高价值`、`精品`、`文笔好` 这种质量标签;质量是准入门槛,不是标签。
224
+
225
+ ### `genres`
226
+
227
+ - 1–3 个,跨题材写 `["通用"]`。
228
+ - 必须原样包含本次主题材名。例如本次是「仙侠·修真文明」,可以写:
229
+
230
+ ```json
231
+ ["仙侠·修真文明", "仙侠", "修真"]
232
+ ```
233
+
234
+ 不能只写 `["仙侠"]` 而丢掉主题材名。
235
+
236
+ ---
237
+
238
+ ## 七、题材来源与优先级
239
+
240
+ - 当前模式:`{{MATERIAL_MODE}}`
241
+ - `topic_decision`:从 `{{TOPIC_FILE}}` 的「选题方向」中提取全部题材。
242
+ - `all_genres`:使用番茄扫榜数据中的全部题材。
243
+ - 本次题材列表:{{GENRES}}
244
+
245
+ 不同题材优先补充的 kind:
246
+
247
+ ```text
248
+ 仙侠/玄幻/修真/高武:faction_name、place_name、skill_name、ability_*、item_*、power_*、rank_name、mythic_being
249
+ 都市异能/都市玄幻:place_name、faction_name、ability_*、world_rule、item_*、person_*
250
+ 末世/科幻:place_name、item_*、monster_name、world_rule、faction_name、sensory_*
251
+ 悬疑/规则怪谈:place_name、world_rule、person_*、reaction、sensory_*、item_*
252
+ 言情/情感:person_*、reaction、sensory_*、location_feature、weather
253
+ ```
254
+
255
+ 所有题材都可以使用全部 kind;上面的列表只是优先级。
256
+
257
+ ---
258
+
259
+ ## 八、目标、批次与追加
260
+
261
+ - **本次运行目标**:队列中的每个 kind **新增** `{{TARGET_PER_KIND}}` 条,追加到现有素材库。
262
+ - 这不是库内上限:库里已经有 `{{TARGET_PER_KIND}}` 条,本次仍要再生成 `{{TARGET_PER_KIND}}` 条新的。
263
+ - 每个 kind 由插件拆成多个批次,每批最多 `{{BATCH_SIZE}}` 条;写完一批就结束本轮,插件会发下一批。
264
+ - 配额只看「本次已生成」,不看「库中已有」;已有素材只用于去重,不要因为库里有同名/同类素材就少写。
265
+ - 一个批次只写一个 kind;不要混写,也不要自行切换到下一个 kind。
266
+ - 只追加,不覆盖;已有素材不得改写、删除或换 id 重写。
267
+ - 同 `kind + name` 已存在就跳过;不要靠换 id 重复同一素材。
268
+ - 不要为了凑数复制、换皮或降低质量;宁可不写,也不要写废名。
269
+ - 中断后再次运行 `/fancy-material` 会开始新一轮配额;已经导入的素材保留。
270
+
271
+ ---
272
+
273
+ ## 九、生成前查询已有素材
274
+
275
+ 优先直接查询数据库:
276
+
277
+ ```bash
278
+ node '{{QUERY_SCRIPT}}' --workspace '{{WORKSPACE}}' --kind place_name --name '归墟' --json
279
+ node '{{QUERY_SCRIPT}}' --workspace '{{WORKSPACE}}' --genre '仙侠·修真文明' --kind color_word --limit 20 --json
280
+ node '{{QUERY_SCRIPT}}' --workspace '{{WORKSPACE}}' --search '残影 高速' --limit 20 --json
281
+ ```
282
+
283
+ 输出一行一个已有素材:`id`、`kind`、`name`、`tags`、`genres`。查到同 `kind` 同 `name` 就换一个。
284
+
285
+ `<工作区>/.fancy-tools/fancy-material/` 下的 `query.js`、`validate.js`、`kinds.js`、`version.json`、`README.txt` 是**只读工具**:
286
+ 不要修改、删除、chmod,也不要另建副本;只按上面的命令执行。重新运行 `/fancy-material` 会刷新它们。
287
+
288
+ 也可以搜索插件生成的已有素材索引:
289
+
290
+ ```text
291
+ {{EXISTING_INDEX}}
292
+ ```
293
+
294
+ 当前本次题材下已有素材:`{{EXISTING_TOTAL}}` 条。
295
+
296
+ ---
297
+
298
+ ## 十、JSONL 格式
299
+
300
+ - 一行一个合法 JSON 对象;不要 Markdown 代码围栏、解释、前后缀。
301
+ - UTF-8,无 BOM;不输出注释、`undefined`、`NaN`、`Infinity`。
302
+ - 字符串中的换行写成 `\n`。
303
+ - `id` 全局唯一,格式 `<kind>_<ascii_slug>_v4`。
304
+ - 同批不得重复 `id`;不要复用已有 id。
305
+ - `source` 固定写 `builtin`;`other` 只用于库外手工导入的自定义素材。
306
+
307
+ 示例:
308
+
309
+ ```json
310
+ {"id":"given_name_yanqiu_v4","kind":"given_name","name":"砚秋","tags":["男","双字","书卷","秋意","克制"],"genres":["悬疑","都市"],"note":"","source":"builtin"}
311
+ {"id":"color_word_rain_soaked_cinnabar_v4","kind":"color_word","name":"被雨泡过的朱砂","tags":["红","暖色","潮湿","旧"],"genres":["悬疑","通用"],"note":"","source":"builtin"}
312
+ {"id":"ability_cost_memory_loss_v4","kind":"ability_cost","name":"每次使用后永久丢失一段与死者无关的等长记忆","tags":["记忆","永久","关系代价","调查"],"genres":["悬疑","都市异能"],"note":"","source":"builtin"}
313
+ {"id":"brainstorm_death_certificate_printshop_v4","kind":"brainstorm","name":"给活人打印死亡证明的打印店","tags":["制度","死亡","悬疑","日常"],"genres":["悬疑"],"note":"","source":"builtin"}
314
+ ```
315
+
316
+ ---
317
+
318
+ ## 十一、生成流程
319
+
320
+ 0. 读取「本次运行」里的本批 kind、本批条数和库中已有数量。
321
+ 1. 对当前 kind,先用查询脚本检查候选名字/词是否已存在。
322
+ 2. 只生成当前 kind 的素材,写进目标文件;达到本批条数就停。
323
+ 3. 运行格式校验脚本:
324
+
325
+ ```bash
326
+ node '{{VALIDATE_SCRIPT}}' '<目标文件>'
327
+ ```
328
+
329
+ 校验失败就按错误修正,直到通过。
330
+ 4. 只回复:`已写入 <目标文件路径>`,然后结束本轮。
331
+ 5. **不要在本轮继续生成下一个 kind**;插件会自动发下一批。
332
+
333
+ 可以直接写 JSONL,也可以使用 Python/Node 生成器:
334
+
335
+ - 生成器脚本放在 `<工作区>/.tmp/`,不要放进 `.fancy-tools/`;
336
+ - 生成器必须输出真正的 JSONL(一行一个对象,UTF-8,无 Markdown);
337
+ - 生成后必须运行 `{{VALIDATE_SCRIPT}}`(可每批一次,最终再跑一次);
338
+ - 不要修改、删除、chmod 或另建 `.fancy-tools/fancy-material/` 下的只读脚本。
339
+
340
+ 如果写错,直接覆盖本批次文件重写;数据库导入只会追加。
341
+
342
+ ---
343
+
344
+ ## 十二、输出前自检
345
+
346
+ 逐条检查:
347
+
348
+ 1. 它能否在 30 秒内变成一个具体画面、动作、规则或人物关系?
349
+ 2. 它是不是“火红、淡红、耀眼、神秘、强大”这类谁都能写的词?
350
+ 3. 它有没有具体参照物、感官、情绪或处境?
351
+ 4. 它能不能脱离当前人物/武器/场景,单独用在别处?
352
+ 5. 它和已有素材是不是同义换皮?
353
+ 6. `tags` 是否 3–8 个、能用于检索?
354
+ 7. `genres` 是否包含本次主题材名?
355
+ 8. 是否只写了当前 kind,没有混入其它 kind?
356
+ 9. `source` 是否固定写成了 `builtin`?
357
+ 10. 是否没有新增字段、没有 Markdown 围栏、JSON 合法?
358
+
359
+ ---
360
+
361
+ ## 十三、禁止输出
362
+
363
+ - “火红、淡红、深红、鲜红、蓝蓝的、雪白、漆黑、耀眼、璀璨、绚丽、神秘、强大”等词典词/空泛词。
364
+ - 完整小说、完整章节、完整剧本。
365
+ - 对生成思路的解释。
366
+ - Markdown 代码围栏、前后缀说明。
367
+ - 多个 JSON 对象放在同一行。
368
+ - 复用已有 `id` 或同 `kind + name`。
369
+ - 把武器、特效、技能名、人物强行绑定成“专属关系”。
370
+ - 为了凑数生成空泛、换皮、重复的素材。
@@ -0,0 +1,94 @@
1
+ -- 网文创作素材库 · 原子素材查询示例
2
+ -- 用法:
3
+ -- surreal sql --endpoint http://127.0.0.1:8000 --user root --pass root \
4
+ -- --namespace fancy --database material_library --multi --pretty < queries.surql
5
+ --
6
+ -- 说明:
7
+ -- - 全文检索针对 name;tags / genres 是精确数组匹配。
8
+ -- - search::score(1) 必须和 @1@ 搭配使用。
9
+
10
+ -- ---------------------------------------------------------------------------
11
+ -- 1. 仙侠题材的地名
12
+ -- ---------------------------------------------------------------------------
13
+ SELECT id, kind, name, tags, genres, search::score(1) AS score
14
+ FROM material
15
+ WHERE kind = 'place_name'
16
+ AND genres CONTAINS '仙侠'
17
+ AND name @1@ '海 尽头 旧城'
18
+ ORDER BY score DESC
19
+ LIMIT 10;
20
+
21
+ -- ---------------------------------------------------------------------------
22
+ -- 2. 悬疑题材的男主角名字
23
+ -- ---------------------------------------------------------------------------
24
+ SELECT id, kind, name, tags, genres
25
+ FROM material
26
+ WHERE kind = 'given_name'
27
+ AND genres CONTAINS '悬疑'
28
+ AND tags CONTAINSANY ['男', '正派']
29
+ ORDER BY name
30
+ LIMIT 20;
31
+
32
+ -- ---------------------------------------------------------------------------
33
+ -- 3. 红色系描写词
34
+ -- ---------------------------------------------------------------------------
35
+ SELECT id, kind, name, tags, genres
36
+ FROM material
37
+ WHERE kind = 'color_word'
38
+ AND tags CONTAINSANY ['红', '暖色']
39
+ ORDER BY name
40
+ LIMIT 20;
41
+
42
+ -- ---------------------------------------------------------------------------
43
+ -- 4. 能力机制 + 代价(分开查)
44
+ -- ---------------------------------------------------------------------------
45
+ SELECT id, kind, name, tags, genres, search::score(1) AS score
46
+ FROM material
47
+ WHERE kind IN ['ability_mechanism', 'ability_cost']
48
+ AND name @1@ '记忆 死者 调查'
49
+ ORDER BY score DESC
50
+ LIMIT 10;
51
+
52
+ -- ---------------------------------------------------------------------------
53
+ -- 5. 人物性格 + 说话风格
54
+ -- ---------------------------------------------------------------------------
55
+ SELECT id, kind, name, tags, genres
56
+ FROM material
57
+ WHERE kind IN ['person_personality', 'person_voice']
58
+ AND tags CONTAINSANY ['克制', '冷感', '短句']
59
+ LIMIT 20;
60
+
61
+ -- ---------------------------------------------------------------------------
62
+ -- 6. 脑洞 / 冲突种子
63
+ -- ---------------------------------------------------------------------------
64
+ SELECT id, kind, name, tags, genres, search::score(1) AS score
65
+ FROM material
66
+ WHERE kind IN ['brainstorm', 'conflict_seed']
67
+ AND name @1@ '死亡 打印 保险'
68
+ ORDER BY score DESC
69
+ LIMIT 10;
70
+
71
+ -- ---------------------------------------------------------------------------
72
+ -- 7. 跨类型全文检索
73
+ -- ---------------------------------------------------------------------------
74
+ SELECT id, kind, name, tags, genres, search::score(1) AS score
75
+ FROM material
76
+ WHERE name @1@ '雨夜 殡仪馆 冷库'
77
+ ORDER BY score DESC
78
+ LIMIT 10;
79
+
80
+ -- ---------------------------------------------------------------------------
81
+ -- 8. 按 kind 统计
82
+ -- ---------------------------------------------------------------------------
83
+ SELECT kind, count() AS n
84
+ FROM material
85
+ GROUP BY kind
86
+ ORDER BY n DESC;
87
+
88
+ -- ---------------------------------------------------------------------------
89
+ -- 9. 外部自定义素材(source=other,kind 不受内置列表限制)
90
+ -- ---------------------------------------------------------------------------
91
+ SELECT id, kind, name, source
92
+ FROM material
93
+ WHERE source = 'other'
94
+ ORDER BY kind, name;
@@ -0,0 +1,14 @@
1
+ {"id":"surname_shen_v4","kind":"surname","name":"沈","tags":["常见","江南","水汽","冷感"],"genres":["悬疑","通用"],"note":"姓氏常见,但和“砚秋”组合后有旧档案感。","source":"builtin"}
2
+ {"id":"given_name_yenqiu_v4","kind":"given_name","name":"砚秋","tags":["男","双字","书卷","秋意","克制"],"genres":["悬疑","都市"],"note":"砚是器物,秋是季节,合起来像把秋天磨成墨。","source":"builtin"}
3
+ {"id":"place_name_guixu_v4","kind":"place_name","name":"归墟","tags":["地名","海","尽头","仙侠","不祥"],"genres":["仙侠","通用"],"note":"传说中海水归流之处,适合做门派禁地或旧战场。","source":"builtin"}
4
+ {"id":"faction_name_leifasi_v4","kind":"faction_name","name":"雷罚司","tags":["宗门","雷系","执法","正派","旧制度"],"genres":["仙侠"],"note":"名字里有“罚”,但真正的权力是解释天雷该落在谁头上。","source":"builtin"}
5
+ {"id":"person_appearance_scar_brow_v4","kind":"person_appearance","name":"右眉一道旧疤,左手总戴黑手套","tags":["男","脸","疤痕","克制","记忆点"],"genres":["悬疑","都市"],"note":"","source":"builtin"}
6
+ {"id":"person_personality_tidy_cuff_v4","kind":"person_personality","name":"越紧张越爱整理袖口","tags":["男","克制","焦虑","小动作","外冷内热"],"genres":["悬疑","都市"],"note":"不写“沉稳”,用动作让读者自己判断。","source":"builtin"}
7
+ {"id":"person_voice_gravel_v4","kind":"person_voice","name":"嗓子像砂纸,句子短,爱说“规矩”","tags":["男","粗粝","短句","守尸人","压迫"],"genres":["悬疑","都市"],"note":"","source":"builtin"}
8
+ {"id":"ability_mechanism_last_frame_v4","kind":"ability_mechanism","name":"触碰死者眼睛,进入他死前最后二十四分钟的主观视角","tags":["感知","死者","回放","调查","不可靠"],"genres":["悬疑","都市异能"],"note":"","source":"builtin"}
9
+ {"id":"ability_cost_memory_loss_v4","kind":"ability_cost","name":"每次使用后永久丢失一段与死者无关的等长记忆","tags":["记忆","永久","关系代价","调查"],"genres":["悬疑","都市异能"],"note":"机制和代价分开成条,方便单独替换。","source":"builtin"}
10
+ {"id":"item_form_bone_knife_v4","kind":"item_form","name":"十八厘米长的骨瓷裁纸刀,刀柄烧着蓝色缠枝纹","tags":["骨瓷","刀","缠枝纹","18厘米","阴冷"],"genres":["悬疑","规则怪谈"],"note":"","source":"builtin"}
11
+ {"id":"color_word_rain_cinnabar_v4","kind":"color_word","name":"被雨泡过的朱砂","tags":["红","暖色","潮湿","旧","低饱和"],"genres":["悬疑","通用"],"note":"不是“火红”,用雨水和朱砂给出材质与处境。","source":"builtin"}
12
+ {"id":"effect_word_cold_white_dust_v4","kind":"effect_word","name":"碎成细屑的冷白","tags":["白","冷","破碎","消散","光效"],"genres":["仙侠","都市高武"],"note":"","source":"builtin"}
13
+ {"id":"conflict_seed_insurance_alibi_v4","kind":"conflict_seed","name":"妻子要保险金救女儿,主角要证明她杀了丈夫","tags":["保险","手术费","两难","真相","家庭"],"genres":["悬疑","社会派"],"note":"双方都有不可退让的目标。","source":"builtin"}
14
+ {"id":"brainstorm_death_printshop_v4","kind":"brainstorm","name":"给活人打印死亡证明的打印店","tags":["制度","死亡","悬疑","日常","高概念"],"genres":["悬疑"],"note":"把日常打印服务和死亡制度拼在一起。","source":"builtin"}
@@ -0,0 +1,46 @@
1
+ -- 网文创作素材库 · 原子素材 schema v6(SurrealDB 2.3+)
2
+ -- 用法:
3
+ -- surreal sql --endpoint http://127.0.0.1:8000 --user root --pass ... \
4
+ -- --namespace fancy --database material_library --multi < schema.surql
5
+
6
+ DEFINE TABLE IF NOT EXISTS material SCHEMAFULL PERMISSIONS FOR select FULL;
7
+
8
+ DEFINE FIELD OVERWRITE source ON material TYPE string DEFAULT 'builtin'
9
+ ASSERT $value IN ['builtin', 'other'];
10
+ DEFINE FIELD OVERWRITE kind ON material TYPE string
11
+ ASSERT ($value IN [
12
+ 'surname', 'given_name', 'nickname', 'place_name', 'faction_name', 'skill_name',
13
+ 'ability_name', 'item_name', 'monster_name', 'mythic_being', 'rank_name', 'person_appearance',
14
+ 'person_temperament', 'person_personality', 'person_habit', 'person_voice',
15
+ 'person_background', 'reaction', 'ability_mechanism', 'ability_activation', 'ability_cost',
16
+ 'ability_limit', 'ability_counter', 'power_source', 'item_form', 'item_material',
17
+ 'item_function', 'item_visual', 'location_feature', 'weather', 'sensory_taste',
18
+ 'sensory_visual', 'color_word', 'light_word', 'sound_word', 'smell_word', 'touch_word',
19
+ 'effect_word', 'speed_word', 'atmosphere_word', 'appearance_word', 'expression_word',
20
+ 'action_verb', 'world_rule', 'faction_culture', 'faction_symbol', 'ritual', 'brainstorm',
21
+ 'conflict_seed', 'conflict_escalation', 'plot_twist', 'mystery_seed', 'payoff_scene', 'trope'
22
+ ] OR $this.source = 'other') AND $value != '';
23
+ DEFINE FIELD OVERWRITE name ON material TYPE string;
24
+ DEFINE FIELD OVERWRITE tags ON material TYPE array<string> DEFAULT [];
25
+ DEFINE FIELD OVERWRITE genres ON material TYPE array<string> DEFAULT [];
26
+ DEFINE FIELD OVERWRITE note ON material TYPE string DEFAULT '';
27
+ DEFINE FIELD OVERWRITE created_at ON material TYPE datetime DEFAULT time::now();
28
+ DEFINE FIELD OVERWRITE updated_at ON material TYPE datetime VALUE time::now();
29
+
30
+ -- 基础检索
31
+ DEFINE INDEX IF NOT EXISTS material_kind ON material FIELDS kind;
32
+ DEFINE INDEX IF NOT EXISTS material_name ON material FIELDS name;
33
+ DEFINE INDEX IF NOT EXISTS material_tags ON material FIELDS tags;
34
+ DEFINE INDEX IF NOT EXISTS material_genres ON material FIELDS genres;
35
+ DEFINE INDEX IF NOT EXISTS material_kind_name_unique ON material FIELDS kind, name UNIQUE;
36
+
37
+ -- 中文全文检索:name 本身就是素材内容
38
+ DEFINE ANALYZER IF NOT EXISTS material_zh
39
+ TOKENIZERS class
40
+ FILTERS lowercase, ngram(1,8);
41
+
42
+ DEFINE INDEX IF NOT EXISTS material_name_search
43
+ ON material
44
+ FIELDS name
45
+ SEARCH ANALYZER material_zh
46
+ BM25(1.2, 0.75);
@@ -0,0 +1,24 @@
1
+ # Optional: expose the workspace MCP server inside DSH.
2
+ #
3
+ # DSH also gets native tools (fancy_workspace / fancy_story_*), so this entry is
4
+ # only needed if you want the exact MCP tool names (mcp__fancy__*) or you are
5
+ # sharing one server with other MCP clients.
6
+ #
7
+ # Install the client bridge in the DSH profile first:
8
+ # pnpm add @deepseek-ai/dsh-mcp-client
9
+ #
10
+ # Then merge this insert list into the profile's cordis.patch.yml and replace
11
+ # the two absolute paths.
12
+ - insert:
13
+ - id: mcp-fancy
14
+ name: '@deepseek-ai/dsh-mcp-client'
15
+ config:
16
+ serverName: fancy
17
+ transport: stdio
18
+ command: node
19
+ args:
20
+ - /absolute/path/to/node_modules/@cloud411716/fancy-webnovel/plugins/fancy-story-builder/storydb/mcp.js
21
+ env:
22
+ FANCY_HOME: /absolute/path/to/workspace
23
+ toolCallTimeoutMs: 120000
24
+ failOnStartupError: false