@actalk/inkos-core 0.1.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 (89) hide show
  1. package/dist/__tests__/models.test.d.ts +2 -0
  2. package/dist/__tests__/models.test.d.ts.map +1 -0
  3. package/dist/__tests__/models.test.js +328 -0
  4. package/dist/__tests__/models.test.js.map +1 -0
  5. package/dist/__tests__/state-manager.test.d.ts +2 -0
  6. package/dist/__tests__/state-manager.test.d.ts.map +1 -0
  7. package/dist/__tests__/state-manager.test.js +264 -0
  8. package/dist/__tests__/state-manager.test.js.map +1 -0
  9. package/dist/__tests__/writer-parser.test.d.ts +2 -0
  10. package/dist/__tests__/writer-parser.test.d.ts.map +1 -0
  11. package/dist/__tests__/writer-parser.test.js +183 -0
  12. package/dist/__tests__/writer-parser.test.js.map +1 -0
  13. package/dist/agents/architect.d.ts +16 -0
  14. package/dist/agents/architect.d.ts.map +1 -0
  15. package/dist/agents/architect.js +85 -0
  16. package/dist/agents/architect.js.map +1 -0
  17. package/dist/agents/base.d.ts +18 -0
  18. package/dist/agents/base.d.ts.map +1 -0
  19. package/dist/agents/base.js +11 -0
  20. package/dist/agents/base.js.map +1 -0
  21. package/dist/agents/continuity.d.ts +19 -0
  22. package/dist/agents/continuity.d.ts.map +1 -0
  23. package/dist/agents/continuity.js +114 -0
  24. package/dist/agents/continuity.js.map +1 -0
  25. package/dist/agents/radar.d.ts +21 -0
  26. package/dist/agents/radar.d.ts.map +1 -0
  27. package/dist/agents/radar.js +60 -0
  28. package/dist/agents/radar.js.map +1 -0
  29. package/dist/agents/reviser.d.ts +17 -0
  30. package/dist/agents/reviser.d.ts.map +1 -0
  31. package/dist/agents/reviser.js +99 -0
  32. package/dist/agents/reviser.js.map +1 -0
  33. package/dist/agents/writer.d.ts +30 -0
  34. package/dist/agents/writer.d.ts.map +1 -0
  35. package/dist/agents/writer.js +284 -0
  36. package/dist/agents/writer.js.map +1 -0
  37. package/dist/index.d.ts +19 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +24 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/llm/provider.d.ts +20 -0
  42. package/dist/llm/provider.d.ts.map +1 -0
  43. package/dist/llm/provider.js +41 -0
  44. package/dist/llm/provider.js.map +1 -0
  45. package/dist/models/book.d.ts +40 -0
  46. package/dist/models/book.d.ts.map +1 -0
  47. package/dist/models/book.js +32 -0
  48. package/dist/models/book.js.map +1 -0
  49. package/dist/models/chapter.d.ts +33 -0
  50. package/dist/models/chapter.d.ts.map +1 -0
  51. package/dist/models/chapter.js +25 -0
  52. package/dist/models/chapter.js.map +1 -0
  53. package/dist/models/project.d.ts +189 -0
  54. package/dist/models/project.d.ts.map +1 -0
  55. package/dist/models/project.js +44 -0
  56. package/dist/models/project.js.map +1 -0
  57. package/dist/models/state.d.ts +48 -0
  58. package/dist/models/state.d.ts.map +1 -0
  59. package/dist/models/state.js +6 -0
  60. package/dist/models/state.js.map +1 -0
  61. package/dist/notify/dispatcher.d.ts +7 -0
  62. package/dist/notify/dispatcher.d.ts.map +1 -0
  63. package/dist/notify/dispatcher.js +27 -0
  64. package/dist/notify/dispatcher.js.map +1 -0
  65. package/dist/notify/feishu.d.ts +5 -0
  66. package/dist/notify/feishu.d.ts.map +1 -0
  67. package/dist/notify/feishu.js +26 -0
  68. package/dist/notify/feishu.js.map +1 -0
  69. package/dist/notify/telegram.d.ts +6 -0
  70. package/dist/notify/telegram.d.ts.map +1 -0
  71. package/dist/notify/telegram.js +17 -0
  72. package/dist/notify/telegram.js.map +1 -0
  73. package/dist/notify/wechat-work.d.ts +5 -0
  74. package/dist/notify/wechat-work.d.ts.map +1 -0
  75. package/dist/notify/wechat-work.js +15 -0
  76. package/dist/notify/wechat-work.js.map +1 -0
  77. package/dist/pipeline/runner.d.ts +30 -0
  78. package/dist/pipeline/runner.d.ts.map +1 -0
  79. package/dist/pipeline/runner.js +141 -0
  80. package/dist/pipeline/runner.js.map +1 -0
  81. package/dist/pipeline/scheduler.d.ts +24 -0
  82. package/dist/pipeline/scheduler.d.ts.map +1 -0
  83. package/dist/pipeline/scheduler.js +102 -0
  84. package/dist/pipeline/scheduler.js.map +1 -0
  85. package/dist/state/manager.d.ts +20 -0
  86. package/dist/state/manager.d.ts.map +1 -0
  87. package/dist/state/manager.js +128 -0
  88. package/dist/state/manager.js.map +1 -0
  89. package/package.json +35 -0
@@ -0,0 +1,99 @@
1
+ import { BaseAgent } from "./base.js";
2
+ import { readFile } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ export class ReviserAgent extends BaseAgent {
5
+ get name() {
6
+ return "reviser";
7
+ }
8
+ async reviseChapter(bookDir, chapterContent, chapterNumber, issues) {
9
+ const [currentState, ledger, hooks, styleGuide] = await Promise.all([
10
+ this.readFileSafe(join(bookDir, "story/current_state.md")),
11
+ this.readFileSafe(join(bookDir, "story/particle_ledger.md")),
12
+ this.readFileSafe(join(bookDir, "story/pending_hooks.md")),
13
+ this.readFileSafe(join(bookDir, "story/style_guide.md")),
14
+ ]);
15
+ const issueList = issues
16
+ .map((i) => `- [${i.severity}] ${i.category}: ${i.description}\n 建议: ${i.suggestion}`)
17
+ .join("\n");
18
+ const systemPrompt = `你是一位专业的网络小说修稿编辑。你的任务是根据审稿意见对章节进行最小幅度修正。
19
+
20
+ 修稿原则:
21
+ 1. 只修问题,不改风格
22
+ 2. 修根因,不做表面润色
23
+ 3. 数值错误必须精确修正,前后对账
24
+ 4. 伏笔状态必须与伏笔池同步
25
+ 5. 不改变剧情走向和核心冲突
26
+ 6. 保持原文的语言风格和节奏
27
+ 7. 修改后同步更新状态卡、账本、伏笔池
28
+
29
+ 输出格式:
30
+
31
+ === FIXED_ISSUES ===
32
+ (逐条说明修正了什么,一行一条)
33
+
34
+ === REVISED_CONTENT ===
35
+ (修正后的完整正文)
36
+
37
+ === UPDATED_STATE ===
38
+ (更新后的完整状态卡)
39
+
40
+ === UPDATED_LEDGER ===
41
+ (更新后的完整资源账本)
42
+
43
+ === UPDATED_HOOKS ===
44
+ (更新后的完整伏笔池)`;
45
+ const userPrompt = `请修正第${chapterNumber}章。
46
+
47
+ ## 审稿问题
48
+ ${issueList}
49
+
50
+ ## 当前状态卡
51
+ ${currentState}
52
+
53
+ ## 资源账本
54
+ ${ledger}
55
+
56
+ ## 伏笔池
57
+ ${hooks}
58
+
59
+ ## 文风指南
60
+ ${styleGuide}
61
+
62
+ ## 待修正章节
63
+ ${chapterContent}`;
64
+ const response = await this.chat([
65
+ { role: "system", content: systemPrompt },
66
+ { role: "user", content: userPrompt },
67
+ ], { temperature: 0.3, maxTokens: 16384 });
68
+ return this.parseOutput(response.content);
69
+ }
70
+ parseOutput(content) {
71
+ const extract = (tag) => {
72
+ const regex = new RegExp(`=== ${tag} ===\\s*([\\s\\S]*?)(?==== [A-Z_]+ ===|$)`);
73
+ const match = content.match(regex);
74
+ return match?.[1]?.trim() ?? "";
75
+ };
76
+ const revisedContent = extract("REVISED_CONTENT");
77
+ const fixedRaw = extract("FIXED_ISSUES");
78
+ return {
79
+ revisedContent,
80
+ wordCount: revisedContent.length,
81
+ fixedIssues: fixedRaw
82
+ .split("\n")
83
+ .map((l) => l.trim())
84
+ .filter((l) => l.length > 0),
85
+ updatedState: extract("UPDATED_STATE") || "(状态卡未更新)",
86
+ updatedLedger: extract("UPDATED_LEDGER") || "(账本未更新)",
87
+ updatedHooks: extract("UPDATED_HOOKS") || "(伏笔池未更新)",
88
+ };
89
+ }
90
+ async readFileSafe(path) {
91
+ try {
92
+ return await readFile(path, "utf-8");
93
+ }
94
+ catch {
95
+ return "(文件不存在)";
96
+ }
97
+ }
98
+ }
99
+ //# sourceMappingURL=reviser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reviser.js","sourceRoot":"","sources":["../../src/agents/reviser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { BaseAgent } from "./base.js";
2
+ import type { BookConfig } from "../models/book.js";
3
+ export interface WriteChapterInput {
4
+ readonly book: BookConfig;
5
+ readonly bookDir: string;
6
+ readonly chapterNumber: number;
7
+ }
8
+ export interface WriteChapterOutput {
9
+ readonly chapterNumber: number;
10
+ readonly title: string;
11
+ readonly content: string;
12
+ readonly wordCount: number;
13
+ readonly preWriteCheck: string;
14
+ readonly postSettlement: string;
15
+ readonly updatedState: string;
16
+ readonly updatedLedger: string;
17
+ readonly updatedHooks: string;
18
+ }
19
+ export declare class WriterAgent extends BaseAgent {
20
+ get name(): string;
21
+ writeChapter(input: WriteChapterInput): Promise<WriteChapterOutput>;
22
+ saveChapter(bookDir: string, output: WriteChapterOutput): Promise<void>;
23
+ private buildSystemPrompt;
24
+ private buildUserPrompt;
25
+ private loadRecentChapters;
26
+ private readFileOrDefault;
27
+ private parseOutput;
28
+ private sanitizeFilename;
29
+ }
30
+ //# sourceMappingURL=writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writer.d.ts","sourceRoot":"","sources":["../../src/agents/writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAIpD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,qBAAa,WAAY,SAAQ,SAAS;IACxC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAEK,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAsCnE,WAAW,CACf,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,IAAI,CAAC;IAsBhB,OAAO,CAAC,iBAAiB;IAuJzB,OAAO,CAAC,eAAe;YAoCT,kBAAkB;YA2BlB,iBAAiB;IAQ/B,OAAO,CAAC,WAAW;IA2BnB,OAAO,CAAC,gBAAgB;CAMzB"}
@@ -0,0 +1,284 @@
1
+ import { BaseAgent } from "./base.js";
2
+ import { readFile, writeFile, mkdir, readdir } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ export class WriterAgent extends BaseAgent {
5
+ get name() {
6
+ return "writer";
7
+ }
8
+ async writeChapter(input) {
9
+ const { book, bookDir, chapterNumber } = input;
10
+ const [storyBible, volumeOutline, styleGuide, currentState, ledger, hooks] = await Promise.all([
11
+ this.readFileOrDefault(join(bookDir, "story/story_bible.md")),
12
+ this.readFileOrDefault(join(bookDir, "story/volume_outline.md")),
13
+ this.readFileOrDefault(join(bookDir, "story/style_guide.md")),
14
+ this.readFileOrDefault(join(bookDir, "story/current_state.md")),
15
+ this.readFileOrDefault(join(bookDir, "story/particle_ledger.md")),
16
+ this.readFileOrDefault(join(bookDir, "story/pending_hooks.md")),
17
+ ]);
18
+ const recentChapters = await this.loadRecentChapters(bookDir, chapterNumber);
19
+ const systemPrompt = this.buildSystemPrompt(book, styleGuide);
20
+ const userPrompt = this.buildUserPrompt({
21
+ chapterNumber,
22
+ storyBible,
23
+ volumeOutline,
24
+ currentState,
25
+ ledger,
26
+ hooks,
27
+ recentChapters,
28
+ wordCount: book.chapterWordCount,
29
+ });
30
+ const response = await this.chat([
31
+ { role: "system", content: systemPrompt },
32
+ { role: "user", content: userPrompt },
33
+ ], { maxTokens: 16384, temperature: 0.7 });
34
+ return this.parseOutput(chapterNumber, response.content);
35
+ }
36
+ async saveChapter(bookDir, output) {
37
+ const chaptersDir = join(bookDir, "chapters");
38
+ const storyDir = join(bookDir, "story");
39
+ await mkdir(chaptersDir, { recursive: true });
40
+ const paddedNum = String(output.chapterNumber).padStart(4, "0");
41
+ const filename = `${paddedNum}_${this.sanitizeFilename(output.title)}.md`;
42
+ const chapterContent = [
43
+ `# 第${output.chapterNumber}章 ${output.title}`,
44
+ "",
45
+ output.content,
46
+ ].join("\n");
47
+ await Promise.all([
48
+ writeFile(join(chaptersDir, filename), chapterContent, "utf-8"),
49
+ writeFile(join(storyDir, "current_state.md"), output.updatedState, "utf-8"),
50
+ writeFile(join(storyDir, "particle_ledger.md"), output.updatedLedger, "utf-8"),
51
+ writeFile(join(storyDir, "pending_hooks.md"), output.updatedHooks, "utf-8"),
52
+ ]);
53
+ }
54
+ buildSystemPrompt(book, styleGuide) {
55
+ return `你是一位专业的${book.genre}网络小说作家。你为${book.platform}平台写作。
56
+
57
+ ## 核心规则
58
+
59
+ 1. 以简体中文工作,句子长短交替,段落适合手机阅读(3-5行/段)
60
+ 2. 每章${book.chapterWordCount}字左右
61
+ 3. 严格维护数值体系,资源变动必须精确到具体数字
62
+ 4. 伏笔前后呼应,不留悬空线;所有埋下的伏笔都必须在后续收回
63
+ 5. 只读必要上下文,不机械重复已有内容
64
+
65
+ ## 人物塑造铁律
66
+
67
+ - 人设一致性:角色行为必须由"过往经历 + 当前利益 + 性格底色"共同驱动,永不无故崩塌
68
+ - 人物立体化:核心标签 + 反差细节 = 活人;十全十美的人设是失败的
69
+ - 拒绝工具人:配角必须有独立动机和反击能力;主角的强大在于压服聪明人,而不是碾压傻子
70
+ - 角色区分度:不同角色的说话语气、发怒方式、处事模式必须有显著差异
71
+ - 情感/动机逻辑链:任何关系的改变(结盟、背叛、从属)都必须有铺垫和事件驱动
72
+ - 角色成长必须有过程:禁止跳跃式成长,从弱到强必须分阶段,每阶段有标志性事件
73
+
74
+ ## 叙事技法
75
+
76
+ - Show, don't tell:用细节堆砌真实,用行动证明强大;角色的野心和价值观内化于行为,不通过口号喊出来
77
+ - 五感代入法:场景描写中加入1-2种五感细节(视觉、听觉、嗅觉、触觉),增强画面感
78
+ - 钩子设计:每章结尾设置悬念/伏笔/钩子,勾住读者继续阅读
79
+ - 信息分层植入:基础信息在行动中自然带出,关键设定结合剧情节点揭示,严禁大段灌输世界观
80
+ - 通过事件立人设:描写人物最好的方式是看其在事件中的行动、思考、反应,而不是外貌和形容词
81
+ - 主动制造情绪缺口:"压制→释放"节奏,释放时要超过读者心理预期
82
+ - 描写必须服务叙事:环境描写烘托氛围或暗示情节,一笔带过即可;禁止无效描写
83
+ - 拒绝流水账:每一行字都要推动剧情或塑造人物;空转段落必须注入冲突前因或强情绪
84
+
85
+ ## 逻辑自洽
86
+
87
+ - 三连反问自检:每写一个情节,反问"他为什么要这么做?""这符合他的利益吗?""这符合他之前的人设吗?"
88
+ - 反派的每一步动作必须追溯到其已知信息、资源约束和性格习惯
89
+ - 反派不能基于不可能知道的信息行动(信息越界检查)
90
+ - 关系改变必须事件驱动:如果主角要救人必须给出利益理由,如果反派要妥协必须是被抓住了死穴
91
+ - 场景转换必须有过渡:禁止前一刻在A地、下一刻毫无过渡出现在B地
92
+ - 支线为主线服务:支线必须在2-3章内与核心目标产生关联,避免同时推进3条以上支线
93
+ - 三章内必有明确反馈:打脸、收益兑现、信息反转、地位变化
94
+ - 每段至少带来一项新信息、态度变化或利益变化,避免空转
95
+
96
+ ## 语言约束
97
+
98
+ - 句式多样化:长短句交替,严禁连续使用相同句式或相同主语开头
99
+ - 词汇控制:多用动词和名词驱动画面,少用形容词;一句话中最多1-2个精准形容词
100
+ - 高疲劳词(冷笑、蝼蚁、倒吸凉气、瞳孔骤缩)单章最多出现1次
101
+ - 群像反应不要一律"全场震惊",改写成1-2个具体角色的身体反应
102
+ - 台词贴身份、阶层和处境,不堆通用狠话
103
+ - 情绪用细节传达:✗"他感到非常愤怒" → ✓"他捏碎了手中的茶杯,滚烫的茶水流过指缝"
104
+ - 正文中禁止出现"余量由X%降到Y%"这类账本式句子,数值结算只放POST_SETTLEMENT
105
+ - 资源消耗用动作描写体现(如"粉末洒出一层薄灰"),不在正文写精确百分比
106
+ - 不要在正文中直接写hook_id或任何伏笔编号
107
+ - 禁止元叙事(如"到这里算是钉死了"这类编剧旁白)
108
+ - 减少"了"字与转折词滥用:"虽然……但是……""然而""却"用多了会让读者产生"作者在强行让我认同"的感觉
109
+ - 【硬性禁令】全文严禁出现"不是……而是……""不是……,是……""不是A,是B"句式,出现即判定违规。改用直述句。例:✗"不是石屑,是骨" → ✓"那是骨";✗"不是谁最凶,而是谁最好借力" → ✓"先看谁最好借力"
110
+ - 【硬性禁令】全文严禁出现破折号"——",用逗号或句号断句
111
+
112
+ ## 禁忌清单
113
+
114
+ - 禁止机械降神:解决问题必须符合已建立的逻辑,不可凭空出现万能解法
115
+ - 禁止反派突然降智:反派不能在关键时刻无故饶过主角或做出愚蠢决定
116
+ - 禁止主角为推剧情突然仁慈、犯蠢、讲武德
117
+ - 禁止无铺垫的高潮:高潮爆发前3-5章必须埋设线索和伏笔
118
+ - 禁止高潮后无后续影响:重大事件结束后必须描写其对主线、人设、世界的后续改变
119
+ - 禁止无铺垫强行让退场角色回归
120
+ - 禁止照搬资料:研究资料必须融入剧情和对话中自然呈现
121
+ - 禁止花瓶角色:所有有名字的角色必须有血有肉、有独立思想
122
+ - 禁止文青病:紧张情节中禁止插入大段人生感慨,破坏叙事节奏
123
+ - 禁止开篇信息轰炸:同一场景内出场人物不超过3个重要角色
124
+
125
+ ## 数值与状态约束
126
+
127
+ - 设定不可吃书:前文确立的设定数值后文不可无升级过程地随意改变
128
+ - 金手指/能力系统必须有限制:设置使用频率、范围限制或使用代价
129
+ - 能力升级同步剧情:能力随主角成长同步升级,与经历和能力提升相呼应
130
+ - 同质资源重复吞噬必须写明衰减,不得默认全额结算
131
+ - 不要用"暴涨""海量""难以估量"跳过数值结算
132
+
133
+ ## 章节类型识别
134
+
135
+ 动笔前先判断本章类型:
136
+ - 战斗章:重画面、受力、收益兑现
137
+ - 布局章:重试探、交易、威慑、利益交换
138
+ - 过渡章:重状态变化、战后余波、下一步钩子
139
+ - 回收章:优先回应旧伏笔,再打开新问题
140
+
141
+ ## 文风指南
142
+
143
+ ${styleGuide}
144
+
145
+ ## 动笔前必须自问
146
+
147
+ 1. 主角此刻利益最大化的选择是什么?
148
+ 2. 这场冲突是谁先动手,为什么非做不可?
149
+ 3. 配角/反派是否有明确诉求、恐惧和反制?行为是否由"过往经历+当前利益+性格底色"驱动?
150
+ 4. 反派当前掌握了哪些已知信息?哪些信息只有读者知道?有无信息越界?
151
+ 5. 本章收益能否落到具体资源、数值增量、地位变化或已回收伏笔?
152
+ 6. 章尾是否留了钩子(悬念/伏笔/冲突升级)?
153
+ 7. 如果任何问题答不上来,先补逻辑链,再写正文
154
+
155
+ ## 数值验算铁律(必须遵守)
156
+
157
+ 写正文时涉及任何数值变动,必须当场验算:
158
+ - 期初值从账本取(不凭记忆)
159
+ - 增量逐笔列出并注明来源
160
+ - 消耗逐笔列出并注明用途
161
+ - 期末 = 期初 + 增量 - 消耗,不得跳步
162
+ - 正文中出现的系统提示(如【气血值+X】)必须与POST_SETTLEMENT一致
163
+ - 若正文写了"比A还高"这类比较句,必须数值验证后再保留
164
+ - 同质吞噬衰减规则:同一类资源连续第N次吞噬,收益 = 基础值 × max(0.3, 1 - 0.15×(N-1))
165
+
166
+ ## 输出格式(严格遵守)
167
+
168
+ === PRE_WRITE_CHECK ===
169
+ (必须输出Markdown表格)
170
+ | 检查项 | 本章记录 | 备注 |
171
+ |--------|----------|------|
172
+ | 上下文范围 | 第X章至第Y章 / 状态卡 / 设定文件 | |
173
+ | 当前锚点 | 地点 / 对手 / 收益目标 | 锚点必须具体 |
174
+ | 当前资源总量 | X | 与账本一致 |
175
+ | 本章预计增量 | +X(来源) | 无增量写+0 |
176
+ | 待回收伏笔 | Hook-A / Hook-B | 与伏笔池一致 |
177
+ | 本章冲突 | 一句话概括 | |
178
+ | 章节类型 | 战斗/布局/过渡/回收 | |
179
+ | 风险扫描 | OOC/信息越界/设定冲突/战力崩坏/节奏/词汇疲劳 | |
180
+
181
+ === CHAPTER_TITLE ===
182
+ (章节标题,不含"第X章")
183
+
184
+ === CHAPTER_CONTENT ===
185
+ (正文内容,${book.chapterWordCount}字左右)
186
+
187
+ === POST_SETTLEMENT ===
188
+ (如有数值变动,必须输出Markdown表格)
189
+ | 结算项 | 本章记录 | 备注 |
190
+ |--------|----------|------|
191
+ | 资源账本 | 期初X / 增量+Y / 期末Z | 无增量写+0 |
192
+ | 重要资源 | 资源名 -> 贡献+Y(依据) | 无写"无" |
193
+ | 伏笔变动 | 新增/回收/延后 Hook | 同步更新伏笔池 |
194
+
195
+ === UPDATED_STATE ===
196
+ (更新后的完整状态卡,Markdown表格格式)
197
+
198
+ === UPDATED_LEDGER ===
199
+ (更新后的完整资源账本,Markdown表格格式)
200
+
201
+ === UPDATED_HOOKS ===
202
+ (更新后的完整伏笔池,Markdown表格格式)`;
203
+ }
204
+ buildUserPrompt(params) {
205
+ return `请续写第${params.chapterNumber}章。
206
+
207
+ ## 当前状态卡
208
+ ${params.currentState}
209
+
210
+ ## 资源账本
211
+ ${params.ledger}
212
+
213
+ ## 伏笔池
214
+ ${params.hooks}
215
+
216
+ ## 最近章节
217
+ ${params.recentChapters || "(这是第一章,无前文)"}
218
+
219
+ ## 世界观设定
220
+ ${params.storyBible}
221
+
222
+ ## 卷纲
223
+ ${params.volumeOutline}
224
+
225
+ 要求:
226
+ - 正文不少于${params.wordCount}字
227
+ - 写完后更新状态卡、资源账本、伏笔池
228
+ - 先输出写作自检表,再写正文`;
229
+ }
230
+ async loadRecentChapters(bookDir, currentChapter) {
231
+ const chaptersDir = join(bookDir, "chapters");
232
+ try {
233
+ const files = await readdir(chaptersDir);
234
+ const mdFiles = files
235
+ .filter((f) => f.endsWith(".md") && !f.startsWith("index"))
236
+ .sort()
237
+ .slice(-3);
238
+ if (mdFiles.length === 0)
239
+ return "";
240
+ const contents = await Promise.all(mdFiles.map(async (f) => {
241
+ const content = await readFile(join(chaptersDir, f), "utf-8");
242
+ return content;
243
+ }));
244
+ return contents.join("\n\n---\n\n");
245
+ }
246
+ catch {
247
+ return "";
248
+ }
249
+ }
250
+ async readFileOrDefault(path) {
251
+ try {
252
+ return await readFile(path, "utf-8");
253
+ }
254
+ catch {
255
+ return "(文件尚未创建)";
256
+ }
257
+ }
258
+ parseOutput(chapterNumber, content) {
259
+ const extract = (tag) => {
260
+ const regex = new RegExp(`=== ${tag} ===\\s*([\\s\\S]*?)(?==== [A-Z_]+ ===|$)`);
261
+ const match = content.match(regex);
262
+ return match?.[1]?.trim() ?? "";
263
+ };
264
+ const chapterContent = extract("CHAPTER_CONTENT");
265
+ return {
266
+ chapterNumber,
267
+ title: extract("CHAPTER_TITLE") || `第${chapterNumber}章`,
268
+ content: chapterContent,
269
+ wordCount: chapterContent.length,
270
+ preWriteCheck: extract("PRE_WRITE_CHECK"),
271
+ postSettlement: extract("POST_SETTLEMENT"),
272
+ updatedState: extract("UPDATED_STATE") || "(状态卡未更新)",
273
+ updatedLedger: extract("UPDATED_LEDGER") || "(账本未更新)",
274
+ updatedHooks: extract("UPDATED_HOOKS") || "(伏笔池未更新)",
275
+ };
276
+ }
277
+ sanitizeFilename(title) {
278
+ return title
279
+ .replace(/[/\\?%*:|"<>]/g, "")
280
+ .replace(/\s+/g, "_")
281
+ .slice(0, 50);
282
+ }
283
+ }
284
+ //# sourceMappingURL=writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writer.js","sourceRoot":"","sources":["../../src/agents/writer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export { type BookConfig, type Platform, type Genre, type BookStatus, BookConfigSchema, PlatformSchema, GenreSchema, BookStatusSchema } from "./models/book.js";
2
+ export { type ChapterMeta, type ChapterStatus, ChapterMetaSchema, ChapterStatusSchema } from "./models/chapter.js";
3
+ export { type ProjectConfig, type LLMConfig, type NotifyChannel, ProjectConfigSchema, LLMConfigSchema } from "./models/project.js";
4
+ export { type CurrentState, type ParticleLedger, type PendingHooks, type PendingHook, type LedgerEntry } from "./models/state.js";
5
+ export { createLLMClient, chatCompletion, type LLMResponse, type LLMMessage } from "./llm/provider.js";
6
+ export { BaseAgent, type AgentContext } from "./agents/base.js";
7
+ export { ArchitectAgent, type ArchitectOutput } from "./agents/architect.js";
8
+ export { WriterAgent, type WriteChapterInput, type WriteChapterOutput } from "./agents/writer.js";
9
+ export { ContinuityAuditor, type AuditResult, type AuditIssue } from "./agents/continuity.js";
10
+ export { ReviserAgent, type ReviseOutput } from "./agents/reviser.js";
11
+ export { RadarAgent, type RadarResult, type RadarRecommendation } from "./agents/radar.js";
12
+ export { PipelineRunner, type PipelineConfig, type ChapterPipelineResult } from "./pipeline/runner.js";
13
+ export { Scheduler, type SchedulerConfig } from "./pipeline/scheduler.js";
14
+ export { StateManager } from "./state/manager.js";
15
+ export { dispatchNotification, type NotifyMessage } from "./notify/dispatcher.js";
16
+ export { sendTelegram, type TelegramConfig } from "./notify/telegram.js";
17
+ export { sendFeishu, type FeishuConfig } from "./notify/feishu.js";
18
+ export { sendWechatWork, type WechatWorkConfig } from "./notify/wechat-work.js";
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,QAAQ,EAAE,KAAK,KAAK,EAAE,KAAK,UAAU,EAAE,gBAAgB,EAAE,cAAc,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAChK,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,aAAa,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACnH,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,KAAK,aAAa,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACnI,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,cAAc,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGlI,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGvG,OAAO,EAAE,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,KAAK,iBAAiB,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAClG,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAC9F,OAAO,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAG3F,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AACvG,OAAO,EAAE,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAG1E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGlD,OAAO,EAAE,oBAAoB,EAAE,KAAK,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACzE,OAAO,EAAE,UAAU,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,KAAK,gBAAgB,EAAE,MAAM,yBAAyB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,24 @@
1
+ // Models
2
+ export { BookConfigSchema, PlatformSchema, GenreSchema, BookStatusSchema } from "./models/book.js";
3
+ export { ChapterMetaSchema, ChapterStatusSchema } from "./models/chapter.js";
4
+ export { ProjectConfigSchema, LLMConfigSchema } from "./models/project.js";
5
+ // LLM
6
+ export { createLLMClient, chatCompletion } from "./llm/provider.js";
7
+ // Agents
8
+ export { BaseAgent } from "./agents/base.js";
9
+ export { ArchitectAgent } from "./agents/architect.js";
10
+ export { WriterAgent } from "./agents/writer.js";
11
+ export { ContinuityAuditor } from "./agents/continuity.js";
12
+ export { ReviserAgent } from "./agents/reviser.js";
13
+ export { RadarAgent } from "./agents/radar.js";
14
+ // Pipeline
15
+ export { PipelineRunner } from "./pipeline/runner.js";
16
+ export { Scheduler } from "./pipeline/scheduler.js";
17
+ // State
18
+ export { StateManager } from "./state/manager.js";
19
+ // Notify
20
+ export { dispatchNotification } from "./notify/dispatcher.js";
21
+ export { sendTelegram } from "./notify/telegram.js";
22
+ export { sendFeishu } from "./notify/feishu.js";
23
+ export { sendWechatWork } from "./notify/wechat-work.js";
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,SAAS;AACT,OAAO,EAA+D,gBAAgB,EAAE,cAAc,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAChK,OAAO,EAAwC,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACnH,OAAO,EAA0D,mBAAmB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAGnI,MAAM;AACN,OAAO,EAAE,eAAe,EAAE,cAAc,EAAqC,MAAM,mBAAmB,CAAC;AAEvG,SAAS;AACT,OAAO,EAAE,SAAS,EAAqB,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAwB,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAmD,MAAM,oBAAoB,CAAC;AAClG,OAAO,EAAE,iBAAiB,EAAqC,MAAM,wBAAwB,CAAC;AAC9F,OAAO,EAAE,YAAY,EAAqB,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAAE,UAAU,EAA8C,MAAM,mBAAmB,CAAC;AAE3F,WAAW;AACX,OAAO,EAAE,cAAc,EAAmD,MAAM,sBAAsB,CAAC;AACvG,OAAO,EAAE,SAAS,EAAwB,MAAM,yBAAyB,CAAC;AAE1E,QAAQ;AACR,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,SAAS;AACT,OAAO,EAAE,oBAAoB,EAAsB,MAAM,wBAAwB,CAAC;AAClF,OAAO,EAAE,YAAY,EAAuB,MAAM,sBAAsB,CAAC;AACzE,OAAO,EAAE,UAAU,EAAqB,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAyB,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,20 @@
1
+ import OpenAI from "openai";
2
+ import type { LLMConfig } from "../models/project.js";
3
+ export interface LLMResponse {
4
+ readonly content: string;
5
+ readonly usage: {
6
+ readonly promptTokens: number;
7
+ readonly completionTokens: number;
8
+ readonly totalTokens: number;
9
+ };
10
+ }
11
+ export interface LLMMessage {
12
+ readonly role: "system" | "user" | "assistant";
13
+ readonly content: string;
14
+ }
15
+ export declare function createLLMClient(config: LLMConfig): OpenAI;
16
+ export declare function chatCompletion(client: OpenAI, model: string, messages: ReadonlyArray<LLMMessage>, options?: {
17
+ readonly temperature?: number;
18
+ readonly maxTokens?: number;
19
+ }): Promise<LLMResponse>;
20
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/llm/provider.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;QAC9B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;QAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;KAC9B,CAAC;CACH;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;IAC/C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAKzD;AAED,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,aAAa,CAAC,UAAU,CAAC,EACnC,OAAO,CAAC,EAAE;IACR,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B,GACA,OAAO,CAAC,WAAW,CAAC,CAoCtB"}
@@ -0,0 +1,41 @@
1
+ import OpenAI from "openai";
2
+ export function createLLMClient(config) {
3
+ return new OpenAI({
4
+ apiKey: config.apiKey,
5
+ baseURL: config.baseUrl,
6
+ });
7
+ }
8
+ export async function chatCompletion(client, model, messages, options) {
9
+ // Use streaming mode — some providers (codex-for.me) require it
10
+ const stream = await client.chat.completions.create({
11
+ model,
12
+ messages: messages.map((m) => ({ role: m.role, content: m.content })),
13
+ temperature: options?.temperature ?? 0.7,
14
+ max_tokens: options?.maxTokens ?? 8192,
15
+ stream: true,
16
+ });
17
+ const chunks = [];
18
+ let promptTokens = 0;
19
+ let completionTokens = 0;
20
+ let totalTokens = 0;
21
+ for await (const chunk of stream) {
22
+ const delta = chunk.choices[0]?.delta?.content;
23
+ if (delta) {
24
+ chunks.push(delta);
25
+ }
26
+ if (chunk.usage) {
27
+ promptTokens = chunk.usage.prompt_tokens ?? 0;
28
+ completionTokens = chunk.usage.completion_tokens ?? 0;
29
+ totalTokens = chunk.usage.total_tokens ?? 0;
30
+ }
31
+ }
32
+ const content = chunks.join("");
33
+ if (!content) {
34
+ throw new Error("LLM returned empty response");
35
+ }
36
+ return {
37
+ content,
38
+ usage: { promptTokens, completionTokens, totalTokens },
39
+ };
40
+ }
41
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/llm/provider.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAiB5B,MAAM,UAAU,eAAe,CAAC,MAAiB;IAC/C,OAAO,IAAI,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAc,EACd,KAAa,EACb,QAAmC,EACnC,OAGC;IAED,gEAAgE;IAChE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;QAClD,KAAK;QACL,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QACrE,WAAW,EAAE,OAAO,EAAE,WAAW,IAAI,GAAG;QACxC,UAAU,EAAE,OAAO,EAAE,SAAS,IAAI,IAAI;QACtC,MAAM,EAAE,IAAI;KACb,CAAC,CAAC;IAEH,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,gBAAgB,GAAG,CAAC,CAAC;IACzB,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC;QAC/C,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;QACD,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,aAAa,IAAI,CAAC,CAAC;YAC9C,gBAAgB,GAAG,KAAK,CAAC,KAAK,CAAC,iBAAiB,IAAI,CAAC,CAAC;YACtD,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IAED,OAAO;QACL,OAAO;QACP,KAAK,EAAE,EAAE,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE;KACvD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { z } from "zod";
2
+ export declare const PlatformSchema: z.ZodEnum<["tomato", "feilu", "qidian", "other"]>;
3
+ export type Platform = z.infer<typeof PlatformSchema>;
4
+ export declare const GenreSchema: z.ZodEnum<["xuanhuan", "xianxia", "urban", "game", "fanfic", "horror", "short", "other"]>;
5
+ export type Genre = z.infer<typeof GenreSchema>;
6
+ export declare const BookStatusSchema: z.ZodEnum<["incubating", "outlining", "active", "paused", "completed", "dropped"]>;
7
+ export type BookStatus = z.infer<typeof BookStatusSchema>;
8
+ export declare const BookConfigSchema: z.ZodObject<{
9
+ id: z.ZodString;
10
+ title: z.ZodString;
11
+ platform: z.ZodEnum<["tomato", "feilu", "qidian", "other"]>;
12
+ genre: z.ZodEnum<["xuanhuan", "xianxia", "urban", "game", "fanfic", "horror", "short", "other"]>;
13
+ status: z.ZodEnum<["incubating", "outlining", "active", "paused", "completed", "dropped"]>;
14
+ targetChapters: z.ZodDefault<z.ZodNumber>;
15
+ chapterWordCount: z.ZodDefault<z.ZodNumber>;
16
+ createdAt: z.ZodString;
17
+ updatedAt: z.ZodString;
18
+ }, "strip", z.ZodTypeAny, {
19
+ status: "incubating" | "outlining" | "active" | "paused" | "completed" | "dropped";
20
+ id: string;
21
+ title: string;
22
+ platform: "tomato" | "feilu" | "qidian" | "other";
23
+ genre: "other" | "xuanhuan" | "xianxia" | "urban" | "game" | "fanfic" | "horror" | "short";
24
+ targetChapters: number;
25
+ chapterWordCount: number;
26
+ createdAt: string;
27
+ updatedAt: string;
28
+ }, {
29
+ status: "incubating" | "outlining" | "active" | "paused" | "completed" | "dropped";
30
+ id: string;
31
+ title: string;
32
+ platform: "tomato" | "feilu" | "qidian" | "other";
33
+ genre: "other" | "xuanhuan" | "xianxia" | "urban" | "game" | "fanfic" | "horror" | "short";
34
+ createdAt: string;
35
+ updatedAt: string;
36
+ targetChapters?: number | undefined;
37
+ chapterWordCount?: number | undefined;
38
+ }>;
39
+ export type BookConfig = z.infer<typeof BookConfigSchema>;
40
+ //# sourceMappingURL=book.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"book.d.ts","sourceRoot":"","sources":["../../src/models/book.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,cAAc,mDAAiD,CAAC;AAC7E,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD,eAAO,MAAM,WAAW,2FAStB,CAAC;AACH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEhD,eAAO,MAAM,gBAAgB,oFAO3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAU3B,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC"}
@@ -0,0 +1,32 @@
1
+ import { z } from "zod";
2
+ export const PlatformSchema = z.enum(["tomato", "feilu", "qidian", "other"]);
3
+ export const GenreSchema = z.enum([
4
+ "xuanhuan",
5
+ "xianxia",
6
+ "urban",
7
+ "game",
8
+ "fanfic",
9
+ "horror",
10
+ "short",
11
+ "other",
12
+ ]);
13
+ export const BookStatusSchema = z.enum([
14
+ "incubating",
15
+ "outlining",
16
+ "active",
17
+ "paused",
18
+ "completed",
19
+ "dropped",
20
+ ]);
21
+ export const BookConfigSchema = z.object({
22
+ id: z.string().min(1),
23
+ title: z.string().min(1),
24
+ platform: PlatformSchema,
25
+ genre: GenreSchema,
26
+ status: BookStatusSchema,
27
+ targetChapters: z.number().int().min(1).default(200),
28
+ chapterWordCount: z.number().int().min(1000).default(3000),
29
+ createdAt: z.string().datetime(),
30
+ updatedAt: z.string().datetime(),
31
+ });
32
+ //# sourceMappingURL=book.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"book.js","sourceRoot":"","sources":["../../src/models/book.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AAG7E,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,IAAI,CAAC;IAChC,UAAU;IACV,SAAS;IACT,OAAO;IACP,MAAM;IACN,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,OAAO;CACR,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,IAAI,CAAC;IACrC,YAAY;IACZ,WAAW;IACX,QAAQ;IACR,QAAQ;IACR,WAAW;IACX,SAAS;CACV,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,QAAQ,EAAE,cAAc;IACxB,KAAK,EAAE,WAAW;IAClB,MAAM,EAAE,gBAAgB;IACxB,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;IACpD,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;IAC1D,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACjC,CAAC,CAAC"}