@actalk/inkos-core 0.1.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/agents/architect.d.ts +3 -3
- package/dist/agents/architect.d.ts.map +1 -1
- package/dist/agents/architect.js +91 -16
- package/dist/agents/architect.js.map +1 -1
- package/dist/agents/base.d.ts +2 -3
- package/dist/agents/base.d.ts.map +1 -1
- package/dist/agents/base.js.map +1 -1
- package/dist/agents/continuity.d.ts +1 -1
- package/dist/agents/continuity.d.ts.map +1 -1
- package/dist/agents/continuity.js +88 -17
- package/dist/agents/continuity.js.map +1 -1
- package/dist/agents/radar-source.d.ts +38 -0
- package/dist/agents/radar-source.d.ts.map +1 -0
- package/dist/agents/radar-source.js +92 -0
- package/dist/agents/radar-source.js.map +1 -0
- package/dist/agents/radar.d.ts +4 -1
- package/dist/agents/radar.d.ts.map +1 -1
- package/dist/agents/radar.js +35 -10
- package/dist/agents/radar.js.map +1 -1
- package/dist/agents/reviser.d.ts +2 -1
- package/dist/agents/reviser.d.ts.map +1 -1
- package/dist/agents/reviser.js +40 -18
- package/dist/agents/reviser.js.map +1 -1
- package/dist/agents/rules-reader.d.ts +26 -0
- package/dist/agents/rules-reader.d.ts.map +1 -0
- package/dist/agents/rules-reader.js +86 -0
- package/dist/agents/rules-reader.js.map +1 -0
- package/dist/agents/writer-prompts.d.ts +5 -0
- package/dist/agents/writer-prompts.d.ts.map +1 -0
- package/dist/agents/writer-prompts.js +289 -0
- package/dist/agents/writer-prompts.js.map +1 -0
- package/dist/agents/writer.d.ts +2 -2
- package/dist/agents/writer.d.ts.map +1 -1
- package/dist/agents/writer.js +31 -165
- package/dist/agents/writer.js.map +1 -1
- package/dist/index.d.ts +9 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/llm/provider.d.ts +41 -2
- package/dist/llm/provider.d.ts.map +1 -1
- package/dist/llm/provider.js +235 -9
- package/dist/llm/provider.js.map +1 -1
- package/dist/models/book-rules.d.ts +112 -0
- package/dist/models/book-rules.d.ts.map +1 -0
- package/dist/models/book-rules.js +45 -0
- package/dist/models/book-rules.js.map +1 -0
- package/dist/models/genre-profile.d.ts +42 -0
- package/dist/models/genre-profile.d.ts.map +1 -0
- package/dist/models/genre-profile.js +25 -0
- package/dist/models/genre-profile.js.map +1 -0
- package/dist/pipeline/agent.d.ts +14 -0
- package/dist/pipeline/agent.d.ts.map +1 -0
- package/dist/pipeline/agent.js +267 -0
- package/dist/pipeline/agent.js.map +1 -0
- package/dist/pipeline/runner.d.ts +51 -2
- package/dist/pipeline/runner.d.ts.map +1 -1
- package/dist/pipeline/runner.js +221 -11
- package/dist/pipeline/runner.js.map +1 -1
- package/genres/horror.md +51 -0
- package/genres/other.md +24 -0
- package/genres/urban.md +53 -0
- package/genres/xianxia.md +46 -0
- package/genres/xuanhuan.md +64 -0
- package/package.json +15 -9
package/dist/agents/radar.js
CHANGED
|
@@ -1,18 +1,43 @@
|
|
|
1
1
|
import { BaseAgent } from "./base.js";
|
|
2
|
+
import { FanqieRadarSource, QidianRadarSource } from "./radar-source.js";
|
|
3
|
+
const DEFAULT_SOURCES = [
|
|
4
|
+
new FanqieRadarSource(),
|
|
5
|
+
new QidianRadarSource(),
|
|
6
|
+
];
|
|
7
|
+
function formatRankingsForPrompt(rankings) {
|
|
8
|
+
const sections = rankings
|
|
9
|
+
.filter((r) => r.entries.length > 0)
|
|
10
|
+
.map((r) => {
|
|
11
|
+
const lines = r.entries.map((e) => `- ${e.title}${e.author ? ` (${e.author})` : ""}${e.category ? ` [${e.category}]` : ""} ${e.extra}`);
|
|
12
|
+
return `### ${r.platform}\n${lines.join("\n")}`;
|
|
13
|
+
});
|
|
14
|
+
return sections.length > 0
|
|
15
|
+
? sections.join("\n\n")
|
|
16
|
+
: "(未能获取到实时排行数据,请基于你的知识分析)";
|
|
17
|
+
}
|
|
2
18
|
export class RadarAgent extends BaseAgent {
|
|
19
|
+
sources;
|
|
20
|
+
constructor(ctx, sources) {
|
|
21
|
+
super(ctx);
|
|
22
|
+
this.sources = sources ?? DEFAULT_SOURCES;
|
|
23
|
+
}
|
|
3
24
|
get name() {
|
|
4
25
|
return "radar";
|
|
5
26
|
}
|
|
6
|
-
async scan(
|
|
7
|
-
const
|
|
27
|
+
async scan() {
|
|
28
|
+
const rankings = await Promise.all(this.sources.map((s) => s.fetch()));
|
|
29
|
+
const rankingsText = formatRankingsForPrompt(rankings);
|
|
30
|
+
const systemPrompt = `你是一个专业的网络小说市场分析师。下面是从各平台实时抓取的排行榜数据,请基于这些真实数据分析市场趋势。
|
|
31
|
+
|
|
32
|
+
## 实时排行榜数据
|
|
8
33
|
|
|
9
|
-
|
|
34
|
+
${rankingsText}
|
|
10
35
|
|
|
11
36
|
分析维度:
|
|
12
|
-
1.
|
|
13
|
-
2.
|
|
14
|
-
3.
|
|
15
|
-
4.
|
|
37
|
+
1. 从排行榜数据中识别当前热门题材和标签
|
|
38
|
+
2. 分析哪些类型的作品占据榜单高位
|
|
39
|
+
3. 发现市场空白和机会点(榜单上缺少但有潜力的方向)
|
|
40
|
+
4. 风险提示(榜单上过度扎堆的题材)
|
|
16
41
|
|
|
17
42
|
输出格式必须为 JSON:
|
|
18
43
|
{
|
|
@@ -22,11 +47,11 @@ export class RadarAgent extends BaseAgent {
|
|
|
22
47
|
"genre": "题材类型",
|
|
23
48
|
"concept": "一句话概念描述",
|
|
24
49
|
"confidence": 0.0-1.0,
|
|
25
|
-
"reasoning": "
|
|
50
|
+
"reasoning": "推荐理由(引用具体榜单数据)",
|
|
26
51
|
"benchmarkTitles": ["对标书1", "对标书2"]
|
|
27
52
|
}
|
|
28
53
|
],
|
|
29
|
-
"marketSummary": "
|
|
54
|
+
"marketSummary": "整体市场概述(基于真实榜单数据)"
|
|
30
55
|
}
|
|
31
56
|
|
|
32
57
|
推荐数量:3-5个,按 confidence 降序排列。`;
|
|
@@ -34,7 +59,7 @@ export class RadarAgent extends BaseAgent {
|
|
|
34
59
|
{ role: "system", content: systemPrompt },
|
|
35
60
|
{
|
|
36
61
|
role: "user",
|
|
37
|
-
content:
|
|
62
|
+
content: `请基于上面的实时排行榜数据,分析当前网文市场热度,给出开书建议。`,
|
|
38
63
|
},
|
|
39
64
|
], { temperature: 0.6, maxTokens: 4096 });
|
|
40
65
|
return this.parseResult(response.content);
|
package/dist/agents/radar.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"radar.js","sourceRoot":"","sources":["../../src/agents/radar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"radar.js","sourceRoot":"","sources":["../../src/agents/radar.ts"],"names":[],"mappings":"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"}
|
package/dist/agents/reviser.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BaseAgent } from "./base.js";
|
|
2
2
|
import type { AuditIssue } from "./continuity.js";
|
|
3
|
+
export type ReviseMode = "polish" | "rewrite" | "rework";
|
|
3
4
|
export interface ReviseOutput {
|
|
4
5
|
readonly revisedContent: string;
|
|
5
6
|
readonly wordCount: number;
|
|
@@ -10,7 +11,7 @@ export interface ReviseOutput {
|
|
|
10
11
|
}
|
|
11
12
|
export declare class ReviserAgent extends BaseAgent {
|
|
12
13
|
get name(): string;
|
|
13
|
-
reviseChapter(bookDir: string, chapterContent: string, chapterNumber: number, issues: ReadonlyArray<AuditIssue
|
|
14
|
+
reviseChapter(bookDir: string, chapterContent: string, chapterNumber: number, issues: ReadonlyArray<AuditIssue>, mode?: ReviseMode, genre?: string): Promise<ReviseOutput>;
|
|
14
15
|
private parseOutput;
|
|
15
16
|
private readFileSafe;
|
|
16
17
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reviser.d.ts","sourceRoot":"","sources":["../../src/agents/reviser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"reviser.d.ts","sourceRoot":"","sources":["../../src/agents/reviser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAKlD,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEzD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC5C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAQD,qBAAa,YAAa,SAAQ,SAAS;IACzC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAEK,aAAa,CACjB,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,EACtB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,aAAa,CAAC,UAAU,CAAC,EACjC,IAAI,GAAE,UAAsB,EAC5B,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,YAAY,CAAC;IAyFxB,OAAO,CAAC,WAAW;YA2BL,YAAY;CAO3B"}
|
package/dist/agents/reviser.js
CHANGED
|
@@ -1,30 +1,53 @@
|
|
|
1
1
|
import { BaseAgent } from "./base.js";
|
|
2
|
+
import { readGenreProfile, readBookRules } from "./rules-reader.js";
|
|
2
3
|
import { readFile } from "node:fs/promises";
|
|
3
4
|
import { join } from "node:path";
|
|
5
|
+
const MODE_DESCRIPTIONS = {
|
|
6
|
+
polish: "润色:只改表达、节奏、段落呼吸,不改事实与剧情结论",
|
|
7
|
+
rewrite: "改写:可改叙述顺序、画面、力度,但保留核心事实与人物动机",
|
|
8
|
+
rework: "重写:可重构场景推进和冲突组织,但不改主设定和大事件结果",
|
|
9
|
+
};
|
|
4
10
|
export class ReviserAgent extends BaseAgent {
|
|
5
11
|
get name() {
|
|
6
12
|
return "reviser";
|
|
7
13
|
}
|
|
8
|
-
async reviseChapter(bookDir, chapterContent, chapterNumber, issues) {
|
|
9
|
-
const [currentState, ledger, hooks,
|
|
14
|
+
async reviseChapter(bookDir, chapterContent, chapterNumber, issues, mode = "rewrite", genre) {
|
|
15
|
+
const [currentState, ledger, hooks, styleGuideRaw] = await Promise.all([
|
|
10
16
|
this.readFileSafe(join(bookDir, "story/current_state.md")),
|
|
11
17
|
this.readFileSafe(join(bookDir, "story/particle_ledger.md")),
|
|
12
18
|
this.readFileSafe(join(bookDir, "story/pending_hooks.md")),
|
|
13
19
|
this.readFileSafe(join(bookDir, "story/style_guide.md")),
|
|
14
20
|
]);
|
|
21
|
+
// Load genre profile and book rules
|
|
22
|
+
const genreId = genre ?? "other";
|
|
23
|
+
const { profile: gp } = await readGenreProfile(this.ctx.projectRoot, genreId);
|
|
24
|
+
const parsedRules = await readBookRules(bookDir);
|
|
25
|
+
const bookRules = parsedRules?.rules ?? null;
|
|
26
|
+
// Fallback: use book_rules body when style_guide.md doesn't exist
|
|
27
|
+
const styleGuide = styleGuideRaw !== "(文件不存在)"
|
|
28
|
+
? styleGuideRaw
|
|
29
|
+
: (parsedRules?.body ?? "(无文风指南)");
|
|
15
30
|
const issueList = issues
|
|
16
31
|
.map((i) => `- [${i.severity}] ${i.category}: ${i.description}\n 建议: ${i.suggestion}`)
|
|
17
32
|
.join("\n");
|
|
18
|
-
const
|
|
33
|
+
const modeDesc = MODE_DESCRIPTIONS[mode];
|
|
34
|
+
const numericalRule = gp.numericalSystem
|
|
35
|
+
? "\n3. 数值错误必须精确修正,前后对账"
|
|
36
|
+
: "";
|
|
37
|
+
const protagonistBlock = bookRules?.protagonist
|
|
38
|
+
? `\n\n主角人设锁定:${bookRules.protagonist.name},${bookRules.protagonist.personalityLock.join("、")}。修改不得违反人设。`
|
|
39
|
+
: "";
|
|
40
|
+
const systemPrompt = `你是一位专业的${gp.name}网络小说修稿编辑。你的任务是根据审稿意见对章节进行修正。${protagonistBlock}
|
|
41
|
+
|
|
42
|
+
修稿模式:${modeDesc}
|
|
19
43
|
|
|
20
44
|
修稿原则:
|
|
21
|
-
1.
|
|
22
|
-
2.
|
|
23
|
-
3. 数值错误必须精确修正,前后对账
|
|
45
|
+
1. 按模式控制修改幅度
|
|
46
|
+
2. 修根因,不做表面润色${numericalRule}
|
|
24
47
|
4. 伏笔状态必须与伏笔池同步
|
|
25
48
|
5. 不改变剧情走向和核心冲突
|
|
26
49
|
6. 保持原文的语言风格和节奏
|
|
27
|
-
7.
|
|
50
|
+
7. 修改后同步更新状态卡${gp.numericalSystem ? "、账本" : ""}、伏笔池
|
|
28
51
|
|
|
29
52
|
输出格式:
|
|
30
53
|
|
|
@@ -36,12 +59,12 @@ export class ReviserAgent extends BaseAgent {
|
|
|
36
59
|
|
|
37
60
|
=== UPDATED_STATE ===
|
|
38
61
|
(更新后的完整状态卡)
|
|
39
|
-
|
|
40
|
-
=== UPDATED_LEDGER ===
|
|
41
|
-
(更新后的完整资源账本)
|
|
42
|
-
|
|
62
|
+
${gp.numericalSystem ? "\n=== UPDATED_LEDGER ===\n(更新后的完整资源账本)" : ""}
|
|
43
63
|
=== UPDATED_HOOKS ===
|
|
44
64
|
(更新后的完整伏笔池)`;
|
|
65
|
+
const ledgerBlock = gp.numericalSystem
|
|
66
|
+
? `\n## 资源账本\n${ledger}`
|
|
67
|
+
: "";
|
|
45
68
|
const userPrompt = `请修正第${chapterNumber}章。
|
|
46
69
|
|
|
47
70
|
## 审稿问题
|
|
@@ -49,10 +72,7 @@ ${issueList}
|
|
|
49
72
|
|
|
50
73
|
## 当前状态卡
|
|
51
74
|
${currentState}
|
|
52
|
-
|
|
53
|
-
## 资源账本
|
|
54
|
-
${ledger}
|
|
55
|
-
|
|
75
|
+
${ledgerBlock}
|
|
56
76
|
## 伏笔池
|
|
57
77
|
${hooks}
|
|
58
78
|
|
|
@@ -65,9 +85,9 @@ ${chapterContent}`;
|
|
|
65
85
|
{ role: "system", content: systemPrompt },
|
|
66
86
|
{ role: "user", content: userPrompt },
|
|
67
87
|
], { temperature: 0.3, maxTokens: 16384 });
|
|
68
|
-
return this.parseOutput(response.content);
|
|
88
|
+
return this.parseOutput(response.content, gp);
|
|
69
89
|
}
|
|
70
|
-
parseOutput(content) {
|
|
90
|
+
parseOutput(content, gp) {
|
|
71
91
|
const extract = (tag) => {
|
|
72
92
|
const regex = new RegExp(`=== ${tag} ===\\s*([\\s\\S]*?)(?==== [A-Z_]+ ===|$)`);
|
|
73
93
|
const match = content.match(regex);
|
|
@@ -83,7 +103,9 @@ ${chapterContent}`;
|
|
|
83
103
|
.map((l) => l.trim())
|
|
84
104
|
.filter((l) => l.length > 0),
|
|
85
105
|
updatedState: extract("UPDATED_STATE") || "(状态卡未更新)",
|
|
86
|
-
updatedLedger:
|
|
106
|
+
updatedLedger: gp.numericalSystem
|
|
107
|
+
? (extract("UPDATED_LEDGER") || "(账本未更新)")
|
|
108
|
+
: "",
|
|
87
109
|
updatedHooks: extract("UPDATED_HOOKS") || "(伏笔池未更新)",
|
|
88
110
|
};
|
|
89
111
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reviser.js","sourceRoot":"","sources":["../../src/agents/reviser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"reviser.js","sourceRoot":"","sources":["../../src/agents/reviser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAItC,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAajC,MAAM,iBAAiB,GAA+B;IACpD,MAAM,EAAE,2BAA2B;IACnC,OAAO,EAAE,8BAA8B;IACvC,MAAM,EAAE,8BAA8B;CACvC,CAAC;AAEF,MAAM,OAAO,YAAa,SAAQ,SAAS;IACzC,IAAI,IAAI;QACN,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,aAAa,CACjB,OAAe,EACf,cAAsB,EACtB,aAAqB,EACrB,MAAiC,EACjC,OAAmB,SAAS,EAC5B,KAAc;QAEd,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACrE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,wBAAwB,CAAC,CAAC;YAC1D,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,0BAA0B,CAAC,CAAC;YAC5D,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,wBAAwB,CAAC,CAAC;YAC1D,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,sBAAsB,CAAC,CAAC;SACzD,CAAC,CAAC;QAEH,oCAAoC;QACpC,MAAM,OAAO,GAAG,KAAK,IAAI,OAAO,CAAC;QACjC,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAC9E,MAAM,WAAW,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC;QACjD,MAAM,SAAS,GAAG,WAAW,EAAE,KAAK,IAAI,IAAI,CAAC;QAE7C,kEAAkE;QAClE,MAAM,UAAU,GAAG,aAAa,KAAK,SAAS;YAC5C,CAAC,CAAC,aAAa;YACf,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,IAAI,SAAS,CAAC,CAAC;QAErC,MAAM,SAAS,GAAG,MAAM;aACrB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,WAAW,WAAW,CAAC,CAAC,UAAU,EAAE,CAAC;aACtF,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,MAAM,QAAQ,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,aAAa,GAAG,EAAE,CAAC,eAAe;YACtC,CAAC,CAAC,sBAAsB;YACxB,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,gBAAgB,GAAG,SAAS,EAAE,WAAW;YAC7C,CAAC,CAAC,cAAc,SAAS,CAAC,WAAW,CAAC,IAAI,IAAI,SAAS,CAAC,WAAW,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY;YACzG,CAAC,CAAC,EAAE,CAAC;QAEP,MAAM,YAAY,GAAG,UAAU,EAAE,CAAC,IAAI,+BAA+B,gBAAgB;;OAElF,QAAQ;;;;eAIA,aAAa;;;;eAIb,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;EAY5C,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,wCAAwC,CAAC,CAAC,CAAC,EAAE;;YAExD,CAAC;QAET,MAAM,WAAW,GAAG,EAAE,CAAC,eAAe;YACpC,CAAC,CAAC,cAAc,MAAM,EAAE;YACxB,CAAC,CAAC,EAAE,CAAC;QAEP,MAAM,UAAU,GAAG,OAAO,aAAa;;;EAGzC,SAAS;;;EAGT,YAAY;EACZ,WAAW;;EAEX,KAAK;;;EAGL,UAAU;;;EAGV,cAAc,EAAE,CAAC;QAEf,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAC9B;YACE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE;YACzC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE;SACtC,EACD,EAAE,WAAW,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,CACvC,CAAC;QAEF,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAChD,CAAC;IAEO,WAAW,CAAC,OAAe,EAAE,EAAgB;QACnD,MAAM,OAAO,GAAG,CAAC,GAAW,EAAU,EAAE;YACtC,MAAM,KAAK,GAAG,IAAI,MAAM,CACtB,OAAO,GAAG,2CAA2C,CACtD,CAAC;YACF,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACnC,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAClC,CAAC,CAAC;QAEF,MAAM,cAAc,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;QAClD,MAAM,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;QAEzC,OAAO;YACL,cAAc;YACd,SAAS,EAAE,cAAc,CAAC,MAAM;YAChC,WAAW,EAAE,QAAQ;iBAClB,KAAK,CAAC,IAAI,CAAC;iBACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;iBACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;YAC9B,YAAY,EAAE,OAAO,CAAC,eAAe,CAAC,IAAI,UAAU;YACpD,aAAa,EAAE,EAAE,CAAC,eAAe;gBAC/B,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,IAAI,SAAS,CAAC;gBAC1C,CAAC,CAAC,EAAE;YACN,YAAY,EAAE,OAAO,CAAC,eAAe,CAAC,IAAI,UAAU;SACrD,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,YAAY,CAAC,IAAY;QACrC,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACvC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type ParsedGenreProfile } from "../models/genre-profile.js";
|
|
2
|
+
import { type ParsedBookRules } from "../models/book-rules.js";
|
|
3
|
+
/**
|
|
4
|
+
* Load genre profile. Lookup order:
|
|
5
|
+
* 1. Project-level: {projectRoot}/genres/{genreId}.md
|
|
6
|
+
* 2. Built-in: packages/core/genres/{genreId}.md
|
|
7
|
+
* 3. Fallback: built-in other.md
|
|
8
|
+
*/
|
|
9
|
+
export declare function readGenreProfile(projectRoot: string, genreId: string): Promise<ParsedGenreProfile>;
|
|
10
|
+
/**
|
|
11
|
+
* List all available genre profiles (project-level + built-in, deduped).
|
|
12
|
+
* Returns array of { id, name, source }.
|
|
13
|
+
*/
|
|
14
|
+
export declare function listAvailableGenres(projectRoot: string): Promise<ReadonlyArray<{
|
|
15
|
+
readonly id: string;
|
|
16
|
+
readonly name: string;
|
|
17
|
+
readonly source: "project" | "builtin";
|
|
18
|
+
}>>;
|
|
19
|
+
/** Return the path to the built-in genres directory. */
|
|
20
|
+
export declare function getBuiltinGenresDir(): string;
|
|
21
|
+
/**
|
|
22
|
+
* Load book_rules.md from the book's story directory.
|
|
23
|
+
* Returns null if the file doesn't exist.
|
|
24
|
+
*/
|
|
25
|
+
export declare function readBookRules(bookDir: string): Promise<ParsedBookRules | null>;
|
|
26
|
+
//# sourceMappingURL=rules-reader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules-reader.d.ts","sourceRoot":"","sources":["../../src/agents/rules-reader.ts"],"names":[],"mappings":"AAGA,OAAO,EAAqB,KAAK,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACxF,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAY/E;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,kBAAkB,CAAC,CAe7B;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,aAAa,CAAC;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAAA;CAAE,CAAC,CAAC,CA+BhH;AAED,wDAAwD;AACxD,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAIpF"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { readFile, readdir } from "node:fs/promises";
|
|
2
|
+
import { join, dirname } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { parseGenreProfile } from "../models/genre-profile.js";
|
|
5
|
+
import { parseBookRules } from "../models/book-rules.js";
|
|
6
|
+
const BUILTIN_GENRES_DIR = join(dirname(fileURLToPath(import.meta.url)), "../../genres");
|
|
7
|
+
async function tryReadFile(path) {
|
|
8
|
+
try {
|
|
9
|
+
return await readFile(path, "utf-8");
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Load genre profile. Lookup order:
|
|
17
|
+
* 1. Project-level: {projectRoot}/genres/{genreId}.md
|
|
18
|
+
* 2. Built-in: packages/core/genres/{genreId}.md
|
|
19
|
+
* 3. Fallback: built-in other.md
|
|
20
|
+
*/
|
|
21
|
+
export async function readGenreProfile(projectRoot, genreId) {
|
|
22
|
+
const projectPath = join(projectRoot, "genres", `${genreId}.md`);
|
|
23
|
+
const builtinPath = join(BUILTIN_GENRES_DIR, `${genreId}.md`);
|
|
24
|
+
const fallbackPath = join(BUILTIN_GENRES_DIR, "other.md");
|
|
25
|
+
const raw = (await tryReadFile(projectPath)) ??
|
|
26
|
+
(await tryReadFile(builtinPath)) ??
|
|
27
|
+
(await tryReadFile(fallbackPath));
|
|
28
|
+
if (!raw) {
|
|
29
|
+
throw new Error(`Genre profile not found for "${genreId}" and fallback "other.md" is missing`);
|
|
30
|
+
}
|
|
31
|
+
return parseGenreProfile(raw);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* List all available genre profiles (project-level + built-in, deduped).
|
|
35
|
+
* Returns array of { id, name, source }.
|
|
36
|
+
*/
|
|
37
|
+
export async function listAvailableGenres(projectRoot) {
|
|
38
|
+
const results = new Map();
|
|
39
|
+
// Built-in genres first
|
|
40
|
+
try {
|
|
41
|
+
const builtinFiles = await readdir(BUILTIN_GENRES_DIR);
|
|
42
|
+
for (const file of builtinFiles) {
|
|
43
|
+
if (!file.endsWith(".md"))
|
|
44
|
+
continue;
|
|
45
|
+
const id = file.replace(/\.md$/, "");
|
|
46
|
+
const raw = await tryReadFile(join(BUILTIN_GENRES_DIR, file));
|
|
47
|
+
if (!raw)
|
|
48
|
+
continue;
|
|
49
|
+
const parsed = parseGenreProfile(raw);
|
|
50
|
+
results.set(id, { id, name: parsed.profile.name, source: "builtin" });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch { /* no builtin dir */ }
|
|
54
|
+
// Project-level genres override
|
|
55
|
+
const projectDir = join(projectRoot, "genres");
|
|
56
|
+
try {
|
|
57
|
+
const projectFiles = await readdir(projectDir);
|
|
58
|
+
for (const file of projectFiles) {
|
|
59
|
+
if (!file.endsWith(".md"))
|
|
60
|
+
continue;
|
|
61
|
+
const id = file.replace(/\.md$/, "");
|
|
62
|
+
const raw = await tryReadFile(join(projectDir, file));
|
|
63
|
+
if (!raw)
|
|
64
|
+
continue;
|
|
65
|
+
const parsed = parseGenreProfile(raw);
|
|
66
|
+
results.set(id, { id, name: parsed.profile.name, source: "project" });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch { /* no project genres dir */ }
|
|
70
|
+
return [...results.values()].sort((a, b) => a.id.localeCompare(b.id));
|
|
71
|
+
}
|
|
72
|
+
/** Return the path to the built-in genres directory. */
|
|
73
|
+
export function getBuiltinGenresDir() {
|
|
74
|
+
return BUILTIN_GENRES_DIR;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Load book_rules.md from the book's story directory.
|
|
78
|
+
* Returns null if the file doesn't exist.
|
|
79
|
+
*/
|
|
80
|
+
export async function readBookRules(bookDir) {
|
|
81
|
+
const raw = await tryReadFile(join(bookDir, "story/book_rules.md"));
|
|
82
|
+
if (!raw)
|
|
83
|
+
return null;
|
|
84
|
+
return parseBookRules(raw);
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=rules-reader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules-reader.js","sourceRoot":"","sources":["../../src/agents/rules-reader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { BookConfig } from "../models/book.js";
|
|
2
|
+
import type { GenreProfile } from "../models/genre-profile.js";
|
|
3
|
+
import type { BookRules } from "../models/book-rules.js";
|
|
4
|
+
export declare function buildWriterSystemPrompt(book: BookConfig, genreProfile: GenreProfile, bookRules: BookRules | null, bookRulesBody: string, genreBody: string, styleGuide: string): string;
|
|
5
|
+
//# sourceMappingURL=writer-prompts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writer-prompts.d.ts","sourceRoot":"","sources":["../../src/agents/writer-prompts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAMzD,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,UAAU,EAChB,YAAY,EAAE,YAAY,EAC1B,SAAS,EAAE,SAAS,GAAG,IAAI,EAC3B,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,MAAM,CAkBR"}
|